summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys-cluster/openais/ChangeLog11
-rw-r--r--sys-cluster/openais/files/openais-0.80.3-Makefile-VARS.patch99
-rw-r--r--sys-cluster/openais/files/openais-0.80.3-Makefile.inc-VARS.patch20
-rw-r--r--sys-cluster/openais/files/openais-0.80.3-r1661.patch6310
-rw-r--r--sys-cluster/openais/openais-0.80.3-r1.ebuild (renamed from sys-cluster/openais/openais-0.80.3.ebuild)12
5 files changed, 6450 insertions, 2 deletions
diff --git a/sys-cluster/openais/ChangeLog b/sys-cluster/openais/ChangeLog
index c33849861376..cb59fc372d18 100644
--- a/sys-cluster/openais/ChangeLog
+++ b/sys-cluster/openais/ChangeLog
@@ -1,6 +1,15 @@
# ChangeLog for sys-cluster/openais
# Copyright 1999-2008 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/sys-cluster/openais/ChangeLog,v 1.3 2008/03/17 16:02:41 xmerlin Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-cluster/openais/ChangeLog,v 1.4 2008/11/21 22:55:48 xmerlin Exp $
+
+*openais-0.80.3-r1 (21 Nov 2008)
+
+ 21 Nov 2008; Christian Zoffoli <xmerlin@gentoo.org>
+ +files/openais-0.80.3-Makefile.inc-VARS.patch,
+ +files/openais-0.80.3-Makefile-VARS.patch,
+ +files/openais-0.80.3-r1661.patch, -openais-0.80.3.ebuild,
+ +openais-0.80.3-r1.ebuild:
+ openais whitetank updated to r1661.
*openais-0.80.3 (17 Mar 2008)
diff --git a/sys-cluster/openais/files/openais-0.80.3-Makefile-VARS.patch b/sys-cluster/openais/files/openais-0.80.3-Makefile-VARS.patch
new file mode 100644
index 000000000000..4b00b2c8eff2
--- /dev/null
+++ b/sys-cluster/openais/files/openais-0.80.3-Makefile-VARS.patch
@@ -0,0 +1,99 @@
+--- openais-0.80.3/Makefile.orig 2008-11-18 19:38:46.000000000 +0100
++++ openais-0.80.3/Makefile 2008-11-18 19:42:08.000000000 +0100
+@@ -29,30 +29,30 @@
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ # THE POSSIBILITY OF SUCH DAMAGE.
+
+-DESTDIR=/usr/local
+-SBINDIR=/usr/sbin
+-INCLUDEDIR=/usr/include/openais
+-INCLUDEDIR_TOTEM=/usr/include/openais/totem
+-INCLUDEDIR_LCR=/usr/include/openais/lcr
+-INCLUDEDIR_SERVICE=/usr/include/openais/service
+-MANDIR=/usr/share/man
++include Makefile.inc
++
++SBINDIR=$(PREFIX)/sbin
++INCLUDEDIR=$(PREFIX)/include/openais
++INCLUDEDIR_TOTEM=$(PREFIX)/include/openais/totem
++INCLUDEDIR_LCR=$(PREFIX)/include/openais/lcr
++INCLUDEDIR_SERVICE=$(PREFIX)/include/openais/service
++MANDIR=$(PREFIX)/share/man
+ ETCDIR=/etc/ais
+-LCRSODIR=/usr/libexec/lcrso
+ ARCH=$(shell uname -m)
+
+ ifeq (,$(findstring 64,$(ARCH)))
+-LIBDIR=/usr/lib/openais
++LIBDIR=$(PREFIX)/lib/openais
+ else
+-LIBDIR=/usr/lib64/openais
++LIBDIR=$(PREFIX)/lib64/openais
+ endif
+ ifeq (s390,$(ARCH))
+-LIBDIR=/usr/lib/openais
++LIBDIR=$(PREFIX)/lib/openais
+ endif
+ ifeq (s390x,$(ARCH))
+-LIBDIR=/usr/lib64/openais
++LIBDIR=$(PREFIX)/lib64/openais
+ endif
+ ifeq (ia64,$(ARCH))
+-LIBDIR=/usr/lib/openais
++LIBDIR=$(PREFIX)/lib/openais
+ endif
+
+ all:
+@@ -105,29 +105,29 @@
+ ln -sf libcfg.so.2.0.0 lib/libcfg.so.2
+ ln -sf libtotem_pg.so.2.0.0 exec/libtotem_pg.so.2
+
+- cp -a lib/libais.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaAmf.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaClm.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaCkpt.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaEvt.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaLck.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaMsg.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libevs.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libcpg.so $(DESTDIR)$(LIBDIR)
+- cp -a lib/libcfg.so $(DESTDIR)$(LIBDIR)
+- cp -a exec/libtotem_pg.so $(DESTDIR)$(LIBDIR)
+-
+- cp -a lib/libais.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaAmf.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaClm.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaCkpt.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaEvt.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaLck.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libSaMsg.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libevs.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libcpg.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a lib/libcfg.so.2 $(DESTDIR)$(LIBDIR)
+- cp -a exec/libtotem_pg.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libais.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaAmf.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaClm.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaCkpt.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaEvt.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaLck.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaMsg.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libevs.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libcpg.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libcfg.so $(DESTDIR)$(LIBDIR)
++ $(CP) -a exec/libtotem_pg.so $(DESTDIR)$(LIBDIR)
++
++ $(CP) -a lib/libais.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaAmf.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaClm.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaCkpt.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaEvt.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaLck.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libSaMsg.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libevs.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libcpg.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a lib/libcfg.so.2 $(DESTDIR)$(LIBDIR)
++ $(CP) -a exec/libtotem_pg.so.2 $(DESTDIR)$(LIBDIR)
+
+ install -m 755 lib/libais.so.2.* $(DESTDIR)$(LIBDIR)
+ install -m 755 lib/libSaAmf.so.2.* $(DESTDIR)$(LIBDIR)
diff --git a/sys-cluster/openais/files/openais-0.80.3-Makefile.inc-VARS.patch b/sys-cluster/openais/files/openais-0.80.3-Makefile.inc-VARS.patch
new file mode 100644
index 000000000000..e5c3e4d51251
--- /dev/null
+++ b/sys-cluster/openais/files/openais-0.80.3-Makefile.inc-VARS.patch
@@ -0,0 +1,20 @@
+--- openais-0.80.3/Makefile.inc.orig 2008-11-18 19:31:13.000000000 +0100
++++ openais-0.80.3/Makefile.inc 2008-11-18 19:32:11.000000000 +0100
+@@ -29,12 +29,17 @@
+ # THE POSSIBILITY OF SUCH DAMAGE.
+ # Basic OS detection
+ #
++CP=cp
++DESTDIR=
++PREFIX=/usr
+ UNAME=$(shell uname)
++LCRSODIR=$(PREFIX)/libexec/lcrso
+
+ ifeq "$(UNAME)" "Linux"
+ OPENAIS_COMPAT=LINUX
+ endif
+ ifeq "$(UNAME)" "Darwin"
++ CP=rsync
+ OPENAIS_COMPAT=DARWIN
+ endif
+ ifneq "" "$(findstring BSD,$(UNAME))"
diff --git a/sys-cluster/openais/files/openais-0.80.3-r1661.patch b/sys-cluster/openais/files/openais-0.80.3-r1661.patch
new file mode 100644
index 000000000000..9aef9687f96e
--- /dev/null
+++ b/sys-cluster/openais/files/openais-0.80.3-r1661.patch
@@ -0,0 +1,6310 @@
+diff -uNr openais-0.80.3/CHANGELOG openais-0.80.3-r1661/CHANGELOG
+--- openais-0.80.3/CHANGELOG 2007-06-26 13:36:38.000000000 +0200
++++ openais-0.80.3-r1661/CHANGELOG 2008-11-17 15:54:04.030604165 +0100
+@@ -1,555 +1,4 @@
+ ------------------------------------------------------------------------
+-r1400 | sdake | 2007-06-26 03:13:19 -0700 (Tue, 26 Jun 2007) | 2 lines
+-
+-Fix compile warning/error on some platforms.
+-
+-------------------------------------------------------------------------
+-r1396 | sdake | 2007-06-25 01:42:58 -0700 (Mon, 25 Jun 2007) | 2 lines
+-
+-Update testckpt program to properly test the checkpoint system.
+-
+-------------------------------------------------------------------------
+-r1395 | sdake | 2007-06-25 01:40:45 -0700 (Mon, 25 Jun 2007) | 3 lines
+-
+-Fix problem where sometimes when a checkpoint section is expired the timer
+-also fires at the same time resulting in a warning.
+-
+-------------------------------------------------------------------------
+-r1394 | sdake | 2007-06-24 20:11:10 -0700 (Sun, 24 Jun 2007) | 2 lines
+-
+-Add cpg_context_get and cpg_context_set man pages.
+-
+-------------------------------------------------------------------------
+-r1393 | sdake | 2007-06-24 20:09:31 -0700 (Sun, 24 Jun 2007) | 2 lines
+-
+-Add cpg_context_get and cpg_context_set api calls.
+-
+-------------------------------------------------------------------------
+-r1392 | sdake | 2007-06-24 20:07:30 -0700 (Sun, 24 Jun 2007) | 2 lines
+-
+-install timer.h file for external service handlers.
+-
+-------------------------------------------------------------------------
+-r1390 | sdake | 2007-06-24 19:52:58 -0700 (Sun, 24 Jun 2007) | 2 lines
+-
+-Tests cpg_local_get functionality.
+-
+-------------------------------------------------------------------------
+-r1389 | sdake | 2007-06-24 19:22:54 -0700 (Sun, 24 Jun 2007) | 3 lines
+-
+-Track timers based upon nanoseconds since epoch and add absolute and relative
+-timers.
+-
+-------------------------------------------------------------------------
+-r1387 | sdake | 2007-06-23 23:33:09 -0700 (Sat, 23 Jun 2007) | 2 lines
+-
+-Update all copyright and email addresses in source tree.
+-
+-------------------------------------------------------------------------
+-r1382 | sdake | 2007-06-12 10:43:15 -0700 (Tue, 12 Jun 2007) | 2 lines
+-
+-Add cpg_local_get to get the local node id.
+-
+-------------------------------------------------------------------------
+-r1372 | sdake | 2007-05-17 13:37:43 -0700 (Thu, 17 May 2007) | 3 lines
+-
+-on 32 bit platforms, the message source conn info could have uninitialized
+-values.
+-
+-------------------------------------------------------------------------
+-r1369 | sdake | 2007-04-24 16:11:56 -0700 (Tue, 24 Apr 2007) | 4 lines
+-
+-This bug was posted via bugzilla and a patch was attached. Essentially
+-the checkpoint retention duration was being verified on a checkpoint
+-open which should be ignored.
+-
+-------------------------------------------------------------------------
+-r1368 | sdake | 2007-04-24 16:11:08 -0700 (Tue, 24 Apr 2007) | 2 lines
+-
+-Fix section iteration size comparison
+-
+-------------------------------------------------------------------------
+-r1364 | sdake | 2007-04-24 16:05:56 -0700 (Tue, 24 Apr 2007) | 2 lines
+-
+-Have totemsrp use the proper ring id file.
+-
+-------------------------------------------------------------------------
+-r1363 | sdake | 2007-04-24 16:05:38 -0700 (Tue, 24 Apr 2007) | 2 lines
+-
+-Fix references to evs_initialize in cpg_initialize man pages
+-
+-------------------------------------------------------------------------
+-r1357 | sdake | 2007-03-21 13:07:58 -0700 (Wed, 21 Mar 2007) | 2 lines
+-
+-Fix some type errors within the AMF service.
+-
+-------------------------------------------------------------------------
+-r1356 | sdake | 2007-03-21 13:07:25 -0700 (Wed, 21 Mar 2007) | 2 lines
+-
+-Patch to fix some documentation errors relating to CPG service.
+-
+-------------------------------------------------------------------------
+-r1344 | sdake | 2006-12-18 09:08:02 -0700 (Mon, 18 Dec 2006) | 2 lines
+-
+-Fix compile warnings about unused variables.
+-
+-------------------------------------------------------------------------
+-r1340 | sdake | 2006-12-18 08:02:48 -0700 (Mon, 18 Dec 2006) | 2 lines
+-
+-Fix unaligned access in totem ip on IA64 architecture.
+-
+-------------------------------------------------------------------------
+-r1339 | sdake | 2006-12-12 11:54:51 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Convert some spaces to tabs.
+-
+-------------------------------------------------------------------------
+-r1338 | sdake | 2006-12-12 11:54:25 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Destroy mutex after it is done being used instead of before it is done being used.
+-
+-------------------------------------------------------------------------
+-r1337 | sdake | 2006-12-12 11:45:25 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Remove return and use pthread_exit instead.
+-
+-------------------------------------------------------------------------
+-r1334 | sdake | 2006-12-12 11:38:51 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Backport comparison of 0 and NULL.
+-
+-------------------------------------------------------------------------
+-r1330 | sdake | 2006-12-12 11:13:54 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Fix argument off by one in instiation of AMF components.
+-
+-------------------------------------------------------------------------
+-r1329 | sdake | 2006-12-12 11:11:07 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Remove unnecessary strdup.
+-
+-------------------------------------------------------------------------
+-r1325 | sdake | 2006-12-12 10:56:17 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Change rundir to /var/lib/openais.
+-
+-------------------------------------------------------------------------
+-r1323 | pcaulfie | 2006-12-12 10:45:50 -0700 (Tue, 12 Dec 2006) | 2 lines
+-
+-Fix ordering of CPG join messages.
+-
+-------------------------------------------------------------------------
+-r1319 | sdake | 2006-12-05 09:34:10 -0700 (Tue, 05 Dec 2006) | 2 lines
+-
+-Increase size of default outbound message queue.
+-
+-------------------------------------------------------------------------
+-r1316 | sdake | 2006-11-29 14:30:58 -0700 (Wed, 29 Nov 2006) | 2 lines
+-
+-Improvements on segfault logging.
+-
+-------------------------------------------------------------------------
+-r1315 | sdake | 2006-11-29 13:56:17 -0700 (Wed, 29 Nov 2006) | 2 lines
+-
+-Fix compile error in libcpg
+-
+-------------------------------------------------------------------------
+-r1314 | sdake | 2006-11-29 13:47:40 -0700 (Wed, 29 Nov 2006) | 2 lines
+-
+-Change rundir to /var/openais otherwise core files and ringid file is deleted
+-
+-------------------------------------------------------------------------
+-r1313 | sdake | 2006-11-29 13:35:32 -0700 (Wed, 29 Nov 2006) | 2 lines
+-
+-Flow control fixes for the CPG service.
+-
+-------------------------------------------------------------------------
+-r1312 | fthomas | 2006-11-23 02:10:19 -0700 (Thu, 23 Nov 2006) | 1 line
+-
+-correct incorrect commit that must use SA_AIS_ERR_LIBRARY instead of ERR_LIBRARY
+-------------------------------------------------------------------------
+-r1311 | fthomas | 2006-11-23 01:49:21 -0700 (Thu, 23 Nov 2006) | 1 line
+-
+-handle case where POLLHUP or POLLERR are not supported by OS
+-------------------------------------------------------------------------
+-r1309 | fthomas | 2006-11-16 10:36:52 -0700 (Thu, 16 Nov 2006) | 1 line
+-
+-set default downcheck value to 1000ms
+-------------------------------------------------------------------------
+-r1308 | fthomas | 2006-11-16 10:34:44 -0700 (Thu, 16 Nov 2006) | 1 line
+-
+-remove invalid code / warnings detected by Intel compiler
+-------------------------------------------------------------------------
+-r1307 | sdake | 2006-11-15 00:23:10 -0700 (Wed, 15 Nov 2006) | 2 lines
+-
+-Remove flow control compile warning.
+-
+-------------------------------------------------------------------------
+-r1306 | sdake | 2006-11-15 00:21:02 -0700 (Wed, 15 Nov 2006) | 2 lines
+-
+-Make clean for makefiles improvement to actually remove all files.
+-
+-------------------------------------------------------------------------
+-r1305 | sdake | 2006-11-15 00:19:37 -0700 (Wed, 15 Nov 2006) | 2 lines
+-
+-Set scheduler SCHED_RR to max priority available in the system.
+-
+-------------------------------------------------------------------------
+-r1300 | sdake | 2006-11-13 10:38:13 -0700 (Mon, 13 Nov 2006) | 2 lines
+-
+-Improve behavior of flow control of CPG service during configuration changes.
+-
+-------------------------------------------------------------------------
+-r1296 | sdake | 2006-11-09 05:34:08 -0700 (Thu, 09 Nov 2006) | 2 lines
+-
+-Remove compile warnings.
+-
+-------------------------------------------------------------------------
+-r1295 | sdake | 2006-11-09 05:26:56 -0700 (Thu, 09 Nov 2006) | 5 lines
+-
+-the totem membership protocol was changed to match specificatoins. The sending
+-join messages now use the local seq id of he ring instead of the maximum seqidsrreceived. This resuls in running of the mp5 test for several hours. Also
+-the consensus timeout was increased to allow for the membership protocol to
+-form a proper membership in network overload situations.
+-
+-------------------------------------------------------------------------
+-r1294 | sdake | 2006-11-08 18:33:06 -0700 (Wed, 08 Nov 2006) | 3 lines
+-
+-Modify location of ringid file and create and chdir to
+-/var/run/openais directory so cores are saved there.
+-
+-------------------------------------------------------------------------
+-r1293 | sdake | 2006-11-08 14:48:20 -0700 (Wed, 08 Nov 2006) | 2 lines
+-
+-Flush output of debug messages on exit or segv.
+-
+-------------------------------------------------------------------------
+-r1288 | sdake | 2006-11-04 15:22:02 -0700 (Sat, 04 Nov 2006) | 2 lines
+-
+-Ported revision 1287 - updated README.devmap
+-
+-------------------------------------------------------------------------
+-r1286 | sdake | 2006-11-03 16:48:53 -0700 (Fri, 03 Nov 2006) | 3 lines
+-
+-Fix problem where checkpoints can't be written afer an unlink opeation occurs
+-and a new node is started.
+-
+-------------------------------------------------------------------------
+-r1284 | sdake | 2006-10-24 13:31:15 -0700 (Tue, 24 Oct 2006) | 3 lines
+-
+-Checkpoint section variables were not properly initialized resulting in
+-segfaults.
+-
+-------------------------------------------------------------------------
+-r1283 | sdake | 2006-10-24 08:39:45 -0700 (Tue, 24 Oct 2006) | 2 lines
+-
+-Fix memory leaks.
+-
+-------------------------------------------------------------------------
+-r1282 | sdake | 2006-10-24 04:28:18 -0700 (Tue, 24 Oct 2006) | 2 lines
+-
+-New generation checkpoint synchronization state machine.
+-
+-------------------------------------------------------------------------
+-r1279 | sdake | 2006-10-23 21:08:57 -0700 (Mon, 23 Oct 2006) | 2 lines
+-
+-Call abort in synchronization service when processing is interrupted.
+-
+-------------------------------------------------------------------------
+-r1278 | sdake | 2006-10-23 20:48:41 -0700 (Mon, 23 Oct 2006) | 2 lines
+-
+-Patch testckpt to use proper section id size.
+-
+-------------------------------------------------------------------------
+-r1277 | sdake | 2006-10-23 20:36:40 -0700 (Mon, 23 Oct 2006) | 2 lines
+-
+-Replace spaces with tabs on two lines.
+-
+-------------------------------------------------------------------------
+-r1276 | sdake | 2006-10-23 20:29:12 -0700 (Mon, 23 Oct 2006) | 2 lines
+-
+-remove makefile debug added accidentally in last patch
+-
+-------------------------------------------------------------------------
+-r1275 | sdake | 2006-10-23 20:28:26 -0700 (Mon, 23 Oct 2006) | 2 lines
+-
+-pthread_mutex_destroy cleanup patch from Fabien
+-
+-------------------------------------------------------------------------
+-r1271 | sdake | 2006-10-19 13:38:22 -0700 (Thu, 19 Oct 2006) | 2 lines
+-
+-Fix errors in ia64 alignment.
+-
+-------------------------------------------------------------------------
+-r1270 | sdake | 2006-10-19 10:43:39 -0700 (Thu, 19 Oct 2006) | 2 lines
+-
+-Resolve IPC segfault.
+-
+-------------------------------------------------------------------------
+-r1269 | sdake | 2006-10-18 16:10:34 -0700 (Wed, 18 Oct 2006) | 2 lines
+-
+-Specific stack size for ia64 architectures required.
+-
+-------------------------------------------------------------------------
+-r1268 | sdake | 2006-10-18 16:09:59 -0700 (Wed, 18 Oct 2006) | 3 lines
+-
+-Align totem deliveries on 4 byte boudnaries to avoid segfaults and warnings
+-on sparc and ia64 architectures.
+-
+-------------------------------------------------------------------------
+-r1267 | sdake | 2006-10-16 09:07:01 -0700 (Mon, 16 Oct 2006) | 2 lines
+-
+-Rework of the checkpoint synchronization system.
+-
+-------------------------------------------------------------------------
+-r1265 | sdake | 2006-10-12 15:24:36 -0700 (Thu, 12 Oct 2006) | 2 lines
+-
+-Only originate one regular token.
+-
+-------------------------------------------------------------------------
+-r1264 | sdake | 2006-10-12 15:23:26 -0700 (Thu, 12 Oct 2006) | 3 lines
+-
+-If the failed_list has zero entries, don't add it as an iovector in join
+-messages.
+-
+-------------------------------------------------------------------------
+-r1263 | sdake | 2006-10-12 15:22:53 -0700 (Thu, 12 Oct 2006) | 3 lines
+-
+-Use the fullset variable instead of the local variable j to make easier code
+-reading.
+-
+-------------------------------------------------------------------------
+-r1262 | sdake | 2006-10-12 15:22:09 -0700 (Thu, 12 Oct 2006) | 2 lines
+-
+-Set the ring sequence number according to the totem specificatoins.
+-
+-------------------------------------------------------------------------
+-r1261 | sdake | 2006-10-12 15:21:42 -0700 (Thu, 12 Oct 2006) | 2 lines
+-
+-Cleanup the way the memb_index variable is handled in the commit token
+-
+-------------------------------------------------------------------------
+-r1260 | sdake | 2006-10-12 15:21:04 -0700 (Thu, 12 Oct 2006) | 3 lines
+-
+-Allocate the retransmission token in instance_initialize instead of
+-totemsrp_initialize
+-
+-------------------------------------------------------------------------
+-r1258 | sdake | 2006-10-09 00:43:45 -0700 (Mon, 09 Oct 2006) | 2 lines
+-
+-Accept commit token in proper cases.
+-
+-------------------------------------------------------------------------
+-r1257 | sdake | 2006-10-09 00:43:04 -0700 (Mon, 09 Oct 2006) | 2 lines
+-
+-Fix subset operation to work properly.
+-
+-------------------------------------------------------------------------
+-r1256 | sdake | 2006-10-09 00:42:36 -0700 (Mon, 09 Oct 2006) | 2 lines
+-
+-Remove some extra debug logging output when in DEBUG mode that is not needed.
+-
+-------------------------------------------------------------------------
+-r1252 | sdake | 2006-10-04 21:11:40 -0700 (Wed, 04 Oct 2006) | 2 lines
+-
+-Print out left members properly from totemsrp.
+-
+-------------------------------------------------------------------------
+-r1248 | sdake | 2006-09-28 11:49:00 -0700 (Thu, 28 Sep 2006) | 2 lines
+-
+-Set the proper size of responses to cpg_mcast messages.
+-
+-------------------------------------------------------------------------
+-r1246 | sdake | 2006-09-27 15:57:03 -0700 (Wed, 27 Sep 2006) | 2 lines
+-
+-Flow control part 2 patch.
+-
+-------------------------------------------------------------------------
+-r1245 | sdake | 2006-09-25 02:41:57 -0700 (Mon, 25 Sep 2006) | 2 lines
+-
+-Add cpgbench tool and group wide flow control services for the cpg service.
+-
+-------------------------------------------------------------------------
+-r1230 | fthomas | 2006-08-28 03:12:25 -0700 (Mon, 28 Aug 2006) | 1 line
+-
+-add missing include for assert
+-------------------------------------------------------------------------
+-r1224 | sdake | 2006-08-21 21:40:26 -0700 (Mon, 21 Aug 2006) | 2 lines
+-
+-Fix up printing of SaNameT and mar_name_t in case it is not null terminated.
+-
+-------------------------------------------------------------------------
+-r1223 | sdake | 2006-08-21 21:39:08 -0700 (Mon, 21 Aug 2006) | 2 lines
+-
+-Fix checkpoints with write size of zero to return INVALID PARAM error code
+-
+-------------------------------------------------------------------------
+-r1217 | sdake | 2006-08-15 21:35:15 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Remove invalid commit.
+-
+-------------------------------------------------------------------------
+-r1213 | sdake | 2006-08-15 21:22:30 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Return ERR_TIMEOUT on zero timeout parameter to saEvtEventChannelOpen.
+-
+-------------------------------------------------------------------------
+-r1212 | sdake | 2006-08-15 18:22:40 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Return ERR_TIMEOUT if timeout parameter is zero in saEvtChannelOpen.
+-
+-------------------------------------------------------------------------
+-r1210 | sdake | 2006-08-15 17:45:14 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Add more scalability by adding a new send_join parameter to openais.
+-
+-------------------------------------------------------------------------
+-r1209 | sdake | 2006-08-15 17:37:54 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Remove warning about assert being undefined by including assert.h.
+-
+-------------------------------------------------------------------------
+-r1205 | sdake | 2006-08-15 17:03:45 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Fix hash collision in cpg service.
+-
+-------------------------------------------------------------------------
+-r1204 | sdake | 2006-08-15 16:57:44 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Install proper shared object files for clm service.
+-
+-------------------------------------------------------------------------
+-r1203 | sdake | 2006-08-15 16:55:44 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-Improve recovery state data output.
+-
+-------------------------------------------------------------------------
+-r1202 | sdake | 2006-08-15 16:53:01 -0700 (Tue, 15 Aug 2006) | 3 lines
+-
+-Improve gather notifications so user knows where gather was entered from. This
+-is useful for debugging.
+-
+-------------------------------------------------------------------------
+-r1201 | sdake | 2006-08-15 16:51:56 -0700 (Tue, 15 Aug 2006) | 2 lines
+-
+-This cleans up some of the error reporting of the testckpt tool.
+-
+-------------------------------------------------------------------------
+-r1198 | sdake | 2006-08-08 08:54:02 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Use braces in the totemip code.
+-
+-------------------------------------------------------------------------
+-r1197 | sdake | 2006-08-08 08:52:49 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Ensure compile with GIVE_INFO gives proper information.
+-
+-------------------------------------------------------------------------
+-r1196 | sdake | 2006-08-08 08:52:05 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Resend the commit token if it is lost
+-
+-------------------------------------------------------------------------
+-r1195 | sdake | 2006-08-08 08:51:03 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Move SYNC output data to DEBUG mode.
+-
+-------------------------------------------------------------------------
+-r1194 | sdake | 2006-08-08 08:49:31 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Give better user error messages when token is lost.
+-
+-------------------------------------------------------------------------
+-r1193 | sdake | 2006-08-08 08:41:44 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Fix checkpoint synchronization.
+-
+-------------------------------------------------------------------------
+-r1192 | sdake | 2006-08-08 08:41:22 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Move notice debug outputs in checkpoint service to debug outputs.
+-
+-------------------------------------------------------------------------
+-r1191 | sdake | 2006-08-08 08:40:05 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Use GNU formatting for printf output
+-
+-------------------------------------------------------------------------
+-r1190 | sdake | 2006-08-08 08:38:08 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Clean header includes from swab code.
+-
+-------------------------------------------------------------------------
+-r1189 | sdake | 2006-08-08 08:35:42 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Fix endian marshalling in YKD service.
+-
+-------------------------------------------------------------------------
+-r1188 | sdake | 2006-08-08 08:35:00 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Cleanup lcr_ifact code.
+-
+-------------------------------------------------------------------------
+-r1187 | sdake | 2006-08-08 08:34:36 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Fix endian marshalling for eventing service.
+-
+-------------------------------------------------------------------------
+-r1186 | sdake | 2006-08-08 08:34:10 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Add endian conversion for evs service.
+-
+-------------------------------------------------------------------------
+-r1185 | sdake | 2006-08-08 08:33:13 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Fix marshalling with CPG service.
+-
+-------------------------------------------------------------------------
+-r1184 | sdake | 2006-08-08 08:32:33 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Fix endian marshalling with clm service.
+-
+-------------------------------------------------------------------------
+-r1183 | sdake | 2006-08-08 08:32:04 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Set proper socket for IPV6 membership add
+-
+-------------------------------------------------------------------------
+-r1182 | sdake | 2006-08-08 08:30:40 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Fix processor count in EVS service so EVS service operates properly.
+-
+-------------------------------------------------------------------------
+-r1181 | sdake | 2006-08-08 08:27:05 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-fix ckpt-rd and ckpt-wr test applications
+-
+-------------------------------------------------------------------------
+-r1180 | sdake | 2006-08-08 08:23:33 -0700 (Tue, 08 Aug 2006) | 2 lines
+-
+-Use worker threads for debug output
+-
+-------------------------------------------------------------------------
+-r1179 | sdake | 2006-08-07 15:50:58 -0700 (Mon, 07 Aug 2006) | 2 lines
+-
+-Unlink header prototype incorrect.
+-
+-------------------------------------------------------------------------
+-r1173 | sdake | 2006-08-02 22:31:34 -0700 (Wed, 02 Aug 2006) | 2 lines
+-
+-Ensure sync_activate is only called once
+-
+-------------------------------------------------------------------------
+-r1155 | sdake | 2006-07-24 22:18:52 -0700 (Mon, 24 Jul 2006) | 2 lines
+-
+-Added whitetank branch.
+-
+-------------------------------------------------------------------------
+-r1153 | sdake | 2006-07-23 18:36:18 -0700 (Sun, 23 Jul 2006) | 2 lines
+-
+-Release of version 0.80 First Whitetank release
+-
+-------------------------------------------------------------------------
+ r1152 | sdake | 2006-07-23 18:34:17 -0700 (Sun, 23 Jul 2006) | 2 lines
+
+ Allow build type of COVERAGE for code coverage analysis
+diff -uNr openais-0.80.3/Makefile openais-0.80.3-r1661/Makefile
+--- openais-0.80.3/Makefile 2007-06-25 05:07:30.000000000 +0200
++++ openais-0.80.3-r1661/Makefile 2008-11-17 15:54:04.030604165 +0100
+@@ -196,4 +196,4 @@
+ install -m 644 man/*.8 $(DESTDIR)$(MANDIR)/man8
+
+ doxygen:
+- doxygen
++ mkdir -p doc/api && doxygen
+diff -uNr openais-0.80.3/README.devmap openais-0.80.3-r1661/README.devmap
+--- openais-0.80.3/README.devmap 2006-11-04 23:22:02.000000000 +0100
++++ openais-0.80.3-r1661/README.devmap 2008-11-17 15:54:04.030604165 +0100
+@@ -1221,3 +1221,91 @@
+ for other people.
+
+ Have fun!
++
++---
++IPC state machine
++
++lib_exit_fn may not use openais_response_send or openais_dispatch_send
++
++state INITIALIZING
++------------------
++receive response end of a library request
++ create conn_io data structure
++ if the connection's UID/GID is invalid
++ conn_io_disconnect
++ send response to conn_io with conn_io's address
++ set conn_io refcnt to 1
++
++receive dispatch end of a library connection with response end conn_io address
++ find matching connection
++ if the connection's UID/GID is invalid
++ conn_io_disconnect
++ send reponse to conn_io
++ create conn_info data structure
++ if conn_io response end is valid
++ store dispatch end of conn_io into conn_info data structure
++ store response conn_io into conn_info data structure
++ set conn_io refcnt to 1
++ call lib_init_fn for service type
++ set conn_info refcnt to 1
++ set state to ACTIVE
++
++event response disconnects and conn_info not bound
++ disconnect connection
++event receive connects and response connection not found
++ disconnect dispatch
++event no dispatch connection within 5 seconds
++ disconnect dispatch
++event disconnect_request
++ set state to DISCONNECT_REQUESTED
++ decrement response conn_io refcnt by 1
++ decrement dispatch conn_io refcnt by 1
++
++state ACTIVE
++------------
++do {
++ increment conn_io refcnt by 1
++ poll
++ if invalid poll set state internal_disconnect_request
++ dispatch library handler functions
++ flush any output that can be flushed
++ decrement conn_io refcnt by 1
++ if state set to DISCONNECT_REQUESTED
++ execute algorithm for disconnect requested state
++}
++
++event internal_disconnect_request
++ set state to DISCONNECT_REQUESTED
++ decrement response conn_io refcnt by 1
++ decrement dispatch conn_io refcnt by 1
++event openais_conn_refcnt_increment
++ increase conn_info reference count by 1
++event openais_conn_refcnt_decrement
++ decrease conn_info reference count by 1
++
++state DISCONNECT_REQUESTED
++--------------------------
++if this is the response conn_io data
++do {
++ if response conn_io refcnt is 0
++ destroy conn_io data structure
++ decrement conn_info reference count
++ exit thread
++ sleep configurable short duration
++}
++
++if this is the dispatch conn_io data
++do {
++ if dispatch conn_io refcnt is 0
++ call lib_exit_fn
++ if successful
++ destroy conn_io data structure
++ decrement conn_info reference count
++ exit thread
++ sleep configurable short duration
++}
++
++when conn_info reference count equals 0
++ free conn_info data structure
++
++
+diff -uNr openais-0.80.3/exec/amf.c openais-0.80.3-r1661/exec/amf.c
+--- openais-0.80.3/exec/amf.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/amf.c 2008-11-17 15:54:02.390605772 +0100
+@@ -480,7 +480,7 @@
+ res_lib.header.id = MESSAGE_RES_AMF_COMPONENTREGISTER;
+ res_lib.header.size = sizeof (struct res_lib_amf_componentregister);
+ res_lib.header.error = error;
+- openais_conn_send_response (
++ openais_response_send (
+ comp->conn, &res_lib, sizeof (struct res_lib_amf_componentregister));
+ }
+ }
+@@ -544,7 +544,7 @@
+ res_lib.header.id = MESSAGE_RES_AMF_RESPONSE;
+ res_lib.header.size = sizeof (struct res_lib_amf_response);
+ res_lib.header.error = retval;
+- openais_conn_send_response (comp->conn, &res_lib, sizeof (res_lib));
++ openais_response_send (comp->conn, &res_lib, sizeof (res_lib));
+ }
+ }
+
+@@ -583,7 +583,7 @@
+ res_lib.header.id = MESSAGE_RES_AMF_COMPONENTREGISTER;
+ res_lib.header.size = sizeof (struct res_lib_amf_componentregister);
+ res_lib.header.error = SA_AIS_ERR_INVALID_PARAM;
+- openais_conn_send_response (
++ openais_response_send (
+ conn, &res_lib, sizeof (struct res_lib_amf_componentregister));
+ }
+ }
+@@ -658,12 +658,13 @@
+ res_lib.header.id = MESSAGE_RES_AMF_HEALTHCHECKSTART;
+ res_lib.header.size = sizeof (res_lib);
+ res_lib.header.error = error;
+- openais_conn_send_response (conn, &res_lib,
++ openais_response_send (conn, &res_lib,
+ sizeof (struct res_lib_amf_healthcheckstart));
+ }
+
+ static void message_handler_req_lib_amf_healthcheckconfirm (
+- void *conn, void *msg)
++ void *conn,
++ void *msg)
+ {
+ struct req_lib_amf_healthcheckconfirm *req_lib = msg;
+ struct res_lib_amf_healthcheckconfirm res_lib;
+@@ -683,7 +684,7 @@
+ res_lib.header.id = MESSAGE_RES_AMF_HEALTHCHECKCONFIRM;
+ res_lib.header.size = sizeof (res_lib);
+ res_lib.header.error = error;
+- openais_conn_send_response (conn, &res_lib, sizeof (res_lib));
++ openais_response_send (conn, &res_lib, sizeof (res_lib));
+ }
+
+ static void message_handler_req_lib_amf_healthcheckstop (
+@@ -706,7 +707,7 @@
+ res_lib.header.id = MESSAGE_RES_AMF_HEALTHCHECKSTOP;
+ res_lib.header.size = sizeof (res_lib);
+ res_lib.header.error = error;
+- openais_conn_send_response (conn, &res_lib, sizeof (res_lib));
++ openais_response_send (conn, &res_lib, sizeof (res_lib));
+ }
+
+ static void message_handler_req_lib_amf_hastateget (void *conn, void *msg)
+@@ -732,7 +733,7 @@
+ res_lib.header.size = sizeof (struct res_lib_amf_hastateget);
+ res_lib.header.error = error;
+
+- openais_conn_send_response (conn, &res_lib,
++ openais_response_send (conn, &res_lib,
+ sizeof (struct res_lib_amf_hastateget));
+ }
+
+@@ -788,7 +789,7 @@
+ if (amfProtectionGroup) {
+ res_lib_amf_protectiongrouptrack.header.error = SA_AIS_OK;
+ }
+- openais_conn_send_response (conn, &res_lib_amf_protectiongrouptrack,
++ openais_response_send (conn, &res_lib_amf_protectiongrouptrack,
+ sizeof (struct res_lib_amf_protectiongrouptrack));
+
+ if (amfProtectionGroup &&
+@@ -848,7 +849,7 @@
+ if (track) {
+ res_lib_amf_protectiongrouptrackstop.header.error = SA_AIS_OK;
+ }
+- openais_conn_send_response (conn, &res_lib_amf_protectiongrouptrackstop,
++ openais_response_send (conn, &res_lib_amf_protectiongrouptrackstop,
+ sizeof (struct res_lib_amf_protectiongrouptrackstop));
+
+ #endif
+@@ -896,7 +897,7 @@
+ res_lib.header.size = sizeof (struct res_lib_amf_componenterrorreport);
+ res_lib.header.id = MESSAGE_RES_AMF_COMPONENTERRORREPORT;
+ res_lib.header.error = SA_AIS_ERR_NOT_EXIST;
+- openais_conn_send_response (conn, &res_lib,
++ openais_response_send (conn, &res_lib,
+ sizeof (struct res_lib_amf_componenterrorreport));
+ }
+ }
+@@ -963,7 +964,7 @@
+ res_lib.header.id = MESSAGE_RES_AMF_RESPONSE;
+ res_lib.header.size = sizeof (struct res_lib_amf_response);
+ res_lib.header.error = retval;
+- openais_conn_send_response (conn, &res_lib, sizeof (res_lib));
++ openais_response_send (conn, &res_lib, sizeof (res_lib));
+ }
+ }
+
+diff -uNr openais-0.80.3/exec/amfcomp.c openais-0.80.3-r1661/exec/amfcomp.c
+--- openais-0.80.3/exec/amfcomp.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/amfcomp.c 2008-11-17 15:54:02.380604445 +0100
+@@ -547,8 +547,8 @@
+ AMF_RESPONSE_COMPONENTTERMINATECALLBACK,
+ component_terminate_callback_data);
+
+- openais_conn_send_response (
+- openais_conn_partner_get (comp->conn),
++ openais_dispatch_send (
++ comp->conn,
+ &res_lib,
+ sizeof (struct res_lib_amf_componentterminatecallback));
+
+@@ -817,8 +817,8 @@
+
+ res_lib_amf_csiremovecallback.csiFlags = 0;
+
+- openais_conn_send_response (
+- openais_conn_partner_get (comp->conn),
++ openais_dispatch_send (
++ comp->conn,
+ &res_lib_amf_csiremovecallback,
+ sizeof (struct res_lib_amf_csiremovecallback));
+ }
+@@ -1011,8 +1011,8 @@
+
+ TRACE8 ("sending healthcheck request to component %s",
+ res_lib.compName.value);
+- openais_conn_send_response (
+- openais_conn_partner_get (healthcheck->comp->conn),
++ openais_dispatch_send (
++ healthcheck->comp->conn,
+ &res_lib, sizeof (struct res_lib_amf_healthcheckcallback));
+ }
+
+@@ -1117,8 +1117,7 @@
+ res_lib->invocation =
+ invocation_create (AMF_RESPONSE_CSISETCALLBACK, csi_assignment);
+
+- openais_conn_send_response (
+- openais_conn_partner_get (comp->conn), res_lib, res_lib->header.size);
++ openais_dispatch_send (comp->conn, res_lib, res_lib->header.size);
+
+ free(p);
+ }
+@@ -1129,11 +1128,14 @@
+
+ if (comp->saAmfCompPresenceState == SA_AMF_PRESENCE_RESTARTING) {
+ comp_presence_state_set (comp, SA_AMF_PRESENCE_INSTANTIATED);
+- } else if (comp->saAmfCompPresenceState == SA_AMF_PRESENCE_INSTANTIATING) {
++ } else
++ if (comp->saAmfCompPresenceState == SA_AMF_PRESENCE_INSTANTIATING) {
+ amf_comp_operational_state_set (comp, SA_AMF_OPERATIONAL_ENABLED);
+ comp_presence_state_set (comp, SA_AMF_PRESENCE_INSTANTIATED);
+- }
+- else {
++ } else
++ if (comp->saAmfCompPresenceState == SA_AMF_PRESENCE_UNINSTANTIATED) {
++ return SA_AIS_ERR_INVALID_PARAM;
++ } else {
+ assert (0);
+ }
+
+@@ -1151,7 +1153,7 @@
+ res_lib.header.size = sizeof (struct res_lib_amf_componenterrorreport);
+ res_lib.header.id = MESSAGE_RES_AMF_COMPONENTERRORREPORT;
+ res_lib.header.error = SA_AIS_OK;
+- openais_conn_send_response (comp->conn, &res_lib, sizeof (res_lib));
++ openais_dispatch_send (comp->conn, &res_lib, sizeof (res_lib));
+ }
+
+ /* report to SU and let it handle the problem */
+diff -uNr openais-0.80.3/exec/cfg.c openais-0.80.3-r1661/exec/cfg.c
+--- openais-0.80.3/exec/cfg.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/cfg.c 2008-11-17 15:54:02.370604375 +0100
+@@ -268,7 +268,7 @@
+ res_lib_cfg_ringreenable.header.id = MESSAGE_RES_CFG_RINGREENABLE;
+ res_lib_cfg_ringreenable.header.size = sizeof (struct res_lib_cfg_ringreenable);
+ res_lib_cfg_ringreenable.header.error = SA_AIS_OK;
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_cfg_ringreenable->source.conn,
+ &res_lib_cfg_ringreenable,
+ sizeof (struct res_lib_cfg_ringreenable));
+@@ -298,7 +298,7 @@
+ res_lib_cfg_ringstatusget.header.error = SA_AIS_OK;
+
+ totempg_ifaces_get (
+- this_ip->nodeid,
++ totempg_my_nodeid_get(),
+ interfaces,
+ &status,
+ &iface_count);
+@@ -312,7 +312,7 @@
+ strcpy ((char *)&res_lib_cfg_ringstatusget.interface_name[i],
+ totem_ip_string);
+ }
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_cfg_ringstatusget,
+ sizeof (struct res_lib_cfg_ringstatusget));
+diff -uNr openais-0.80.3/exec/ckpt.c openais-0.80.3-r1661/exec/ckpt.c
+--- openais-0.80.3/exec/ckpt.c 2007-06-26 13:16:50.000000000 +0200
++++ openais-0.80.3-r1661/exec/ckpt.c 2008-11-17 15:54:02.390605772 +0100
+@@ -1,6 +1,6 @@
+ /*
+ * Copyright (c) 2003-2006 MontaVista Software, Inc.
+- * Copyright (c) 2006-2007 Red Hat, Inc.
++ * Copyright (c) 2006-2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+@@ -65,6 +65,8 @@
+ #include "totempg.h"
+ #include "print.h"
+
++#define GLOBALID_CHECKPOINT_NAME "global_checkpoint_name_do_not_use_in_an_application"
++
+ #define CKPT_MAX_SECTION_DATA_SEND (1024*400)
+
+ enum ckpt_message_req_types {
+@@ -92,6 +94,9 @@
+ };
+
+ enum sync_state {
++ SYNC_STATE_NOT_STARTED,
++ SYNC_STATE_STARTED,
++ SYNC_STATE_GLOBALID,
+ SYNC_STATE_CHECKPOINT,
+ SYNC_STATE_REFCOUNT
+ };
+@@ -156,6 +161,7 @@
+
+ struct checkpoint {
+ struct list_head list;
++ struct list_head expiry_list;
+ mar_name_t name;
+ mar_uint32_t ckpt_id;
+ mar_ckpt_checkpoint_creation_attributes_t checkpoint_creation_attributes;
+@@ -367,21 +373,27 @@
+
+ DECLARE_LIST_INIT(checkpoint_recovery_list_head);
+
++DECLARE_LIST_INIT(my_checkpoint_expiry_list_head);
++
+ static mar_uint32_t global_ckpt_id = 0;
+
+-static enum sync_state my_sync_state;
++static enum sync_state my_sync_state = SYNC_STATE_NOT_STARTED;
+
+ static enum iteration_state my_iteration_state;
+
+-static struct list_head *my_iteration_state_checkpoint;
++static struct list_head *my_iteration_state_checkpoint_list;
++
++static struct list_head *my_iteration_state_section_list;
+
+-static struct list_head *my_iteration_state_section;
++static unsigned int my_old_member_list[PROCESSOR_COUNT_MAX];
+
+-static unsigned int my_member_list[PROCESSOR_COUNT_MAX];
++static unsigned int my_old_member_list_entries = 0;
+
+-static unsigned int my_member_list_entries = 0;
++static unsigned int my_should_sync = 0;
+
+-static unsigned int my_lowest_nodeid = 0;
++static unsigned int my_token_callback_active = 0;
++
++static void * my_token_callback_handle;
+
+ struct checkpoint_cleanup {
+ struct list_head list;
+@@ -756,51 +768,11 @@
+ mar_refcount_set_t refcount_set[PROCESSOR_COUNT_MAX] __attribute__((aligned(8)));
+ };
+
++static int first_configuration = 1;
++
+ /*
+ * Implementation
+ */
+-
+-void clean_checkpoint_list(struct list_head *head)
+-{
+- struct list_head *checkpoint_list;
+- struct checkpoint *checkpoint;
+-
+- if (list_empty(head)) {
+- log_printf (LOG_LEVEL_DEBUG, "clean_checkpoint_list: List is empty \n");
+- return;
+- }
+-
+- checkpoint_list = head->next;
+- while (checkpoint_list != head) {
+- checkpoint = list_entry (checkpoint_list,
+- struct checkpoint, list);
+- assert (checkpoint > 0);
+-
+- /*
+- * If checkpoint has been unlinked and this is the last reference, delete it
+- */
+- if (checkpoint->unlinked && checkpoint->reference_count == 0) {
+- log_printf (LOG_LEVEL_DEBUG,"clean_checkpoint_list: deallocating checkpoint %s.\n",
+- checkpoint->name.value);
+- checkpoint_list = checkpoint_list->next;
+- checkpoint_release (checkpoint);
+- continue;
+-
+- }
+- else if (checkpoint->reference_count == 0) {
+- log_printf (LOG_LEVEL_DEBUG, "clean_checkpoint_list: Starting timer to release checkpoint %s.\n",
+- checkpoint->name.value);
+- openais_timer_delete (checkpoint->retention_timer);
+- openais_timer_add_duration (
+- checkpoint->checkpoint_creation_attributes.retention_duration,
+- checkpoint,
+- timer_function_retention,
+- &checkpoint->retention_timer);
+- }
+- checkpoint_list = checkpoint_list->next;
+- }
+-}
+-
+ static void ckpt_confchg_fn (
+ enum totem_configuration_type configuration_type,
+ unsigned int *member_list, int member_list_entries,
+@@ -809,40 +781,45 @@
+ struct memb_ring_id *ring_id)
+ {
+ unsigned int i, j;
++ unsigned int lowest_nodeid;
++
++ memcpy (&my_saved_ring_id, ring_id,
++ sizeof (struct memb_ring_id));
++ if (configuration_type != TOTEM_CONFIGURATION_REGULAR) {
++ return;
++ }
++ if (my_sync_state != SYNC_STATE_NOT_STARTED) {
++ return;
++ }
++
++ my_sync_state = SYNC_STATE_STARTED;
++
++ my_should_sync = 0;
+
+ /*
+- * Determine lowest nodeid in old regular configuration for the
+- * purpose of executing the synchronization algorithm
++ * Handle regular configuration
+ */
+- if (configuration_type == TOTEM_CONFIGURATION_TRANSITIONAL) {
+- for (i = 0; i < left_list_entries; i++) {
+- for (j = 0; j < my_member_list_entries; j++) {
+- if (left_list[i] == my_member_list[j]) {
+- my_member_list[j] = 0;
++ lowest_nodeid = 0xffffffff;
++
++ for (i = 0; i < my_old_member_list_entries; i++) {
++ for (j = 0; j < member_list_entries; j++) {
++ if (my_old_member_list[i] == member_list[j]) {
++ if (lowest_nodeid > member_list[j]) {
++ lowest_nodeid = member_list[j];
+ }
+ }
+- }
+- }
+-
+- my_lowest_nodeid = 0xffffffff;
+- for (i = 0; i < my_member_list_entries; i++) {
+- if ((my_member_list[i] != 0) &&
+- (my_member_list[i] < my_lowest_nodeid)) {
+-
+- my_lowest_nodeid = my_member_list[i];
+ }
+ }
++ memcpy (my_old_member_list, member_list,
++ sizeof (unsigned int) * member_list_entries);
++ my_old_member_list_entries = member_list_entries;
+
+- /*
+- * Handle regular configuration
+- */
+- if (configuration_type == TOTEM_CONFIGURATION_REGULAR) {
+- memcpy (my_member_list, member_list,
+- sizeof (unsigned int) * member_list_entries);
+- my_member_list_entries = member_list_entries;
+- memcpy (&my_saved_ring_id, ring_id,
+- sizeof (struct memb_ring_id));
++ if ((first_configuration) ||
++ (lowest_nodeid == totempg_my_nodeid_get())) {
++
++ my_should_sync = 1;
+ }
++ first_configuration = 0;
+ }
+
+ static struct checkpoint *checkpoint_find (
+@@ -1057,9 +1034,7 @@
+ iovec.iov_base = (char *)&req_exec_ckpt_checkpointclose;
+ iovec.iov_len = sizeof (req_exec_ckpt_checkpointclose);
+
+- assert (totempg_groups_mcast_joined (openais_group_handle, &iovec, 1, TOTEMPG_AGREED) == 0);
+-
+- return (-1);
++ return (totempg_groups_mcast_joined (openais_group_handle, &iovec, 1, TOTEMPG_AGREED));
+ }
+
+ static int ckpt_exec_init_fn (struct objdb_iface_ver0 *objdb)
+@@ -1301,6 +1276,7 @@
+ checkpoint->unlinked = 0;
+ list_init (&checkpoint->list);
+ list_init (&checkpoint->sections_list_head);
++ list_init (&checkpoint->expiry_list);
+ list_add (&checkpoint->list, &checkpoint_list_head);
+ checkpoint->reference_count = 1;
+ checkpoint->retention_timer = 0;
+@@ -1401,12 +1377,12 @@
+ res_lib_ckpt_checkpointopenasync.ckpt_id = checkpoint->ckpt_id;
+ }
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_checkpointopen->source.conn,
+ &res_lib_ckpt_checkpointopenasync,
+ sizeof (struct res_lib_ckpt_checkpointopenasync));
+- openais_conn_send_response (
+- openais_conn_partner_get (req_exec_ckpt_checkpointopen->source.conn),
++ openais_dispatch_send (
++ req_exec_ckpt_checkpointopen->source.conn,
+ &res_lib_ckpt_checkpointopenasync,
+ sizeof (struct res_lib_ckpt_checkpointopenasync));
+ } else {
+@@ -1420,7 +1396,7 @@
+ }
+ res_lib_ckpt_checkpointopen.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_checkpointopen->source.conn,
+ &res_lib_ckpt_checkpointopen,
+ sizeof (struct res_lib_ckpt_checkpointopen));
+@@ -1513,29 +1489,67 @@
+
+ }
+
+-void timer_function_retention (void *data)
++int callback_expiry (enum totem_callback_token_type type, void *data)
+ {
+ struct checkpoint *checkpoint = (struct checkpoint *)data;
+- struct req_exec_ckpt_checkpointretentiondurationexpire req_exec_ckpt_checkpointretentiondurationexpire;
++ struct req_exec_ckpt_checkpointunlink req_exec_ckpt_checkpointunlink;
+ struct iovec iovec;
++ unsigned int res;
++ struct list_head *list;
+
+- checkpoint->retention_timer = 0;
+- req_exec_ckpt_checkpointretentiondurationexpire.header.size =
+- sizeof (struct req_exec_ckpt_checkpointretentiondurationexpire);
+- req_exec_ckpt_checkpointretentiondurationexpire.header.id =
+- SERVICE_ID_MAKE (CKPT_SERVICE,
+- MESSAGE_REQ_EXEC_CKPT_CHECKPOINTRETENTIONDURATIONEXPIRE);
++ list = my_checkpoint_expiry_list_head.next;
++ while (!list_empty(&my_checkpoint_expiry_list_head)) {
++ checkpoint = list_entry (list,
++ struct checkpoint, expiry_list);
+
+- memcpy (&req_exec_ckpt_checkpointretentiondurationexpire.checkpoint_name,
+- &checkpoint->name,
+- sizeof (mar_name_t));
+- req_exec_ckpt_checkpointretentiondurationexpire.ckpt_id =
+- checkpoint->ckpt_id;
++ if (checkpoint->reference_count == 0) {
++ req_exec_ckpt_checkpointunlink.header.size =
++ sizeof (struct req_exec_ckpt_checkpointunlink);
++ req_exec_ckpt_checkpointunlink.header.id =
++ SERVICE_ID_MAKE (CKPT_SERVICE,
++ MESSAGE_REQ_EXEC_CKPT_CHECKPOINTUNLINK);
++
++ req_exec_ckpt_checkpointunlink.source.conn = 0;
++ req_exec_ckpt_checkpointunlink.source.nodeid = 0;
++
++ memcpy (&req_exec_ckpt_checkpointunlink.checkpoint_name,
++ &checkpoint->name,
++ sizeof (mar_name_t));
++
++ iovec.iov_base = (char *)&req_exec_ckpt_checkpointunlink;
++ iovec.iov_len = sizeof (req_exec_ckpt_checkpointunlink);
++
++ res = totempg_groups_mcast_joined (openais_group_handle, &iovec, 1, TOTEMPG_AGREED);
++ if (res == -1) {
++ return (-1);
++ }
++ log_printf (LOG_LEVEL_DEBUG,
++ "Expiring checkpoint %s\n",
++ get_mar_name_t (&checkpoint->name));
++ }
+
+- iovec.iov_base = (char *)&req_exec_ckpt_checkpointretentiondurationexpire;
+- iovec.iov_len = sizeof (req_exec_ckpt_checkpointretentiondurationexpire);
++ list_del (&checkpoint->expiry_list);
++ list = my_checkpoint_expiry_list_head.next;
++ }
++ my_token_callback_active = 0;
++ return (0);
++}
+
+- assert (totempg_groups_mcast_joined (openais_group_handle, &iovec, 1, TOTEMPG_AGREED) == 0);
++void timer_function_retention (void *data)
++{
++ struct checkpoint *checkpoint = (struct checkpoint *)data;
++ checkpoint->retention_timer = 0;
++ list_add (&checkpoint->expiry_list, &my_checkpoint_expiry_list_head);
++
++ if (my_token_callback_active == 0) {
++ totempg_callback_token_create (
++ &my_token_callback_handle,
++ TOTEM_CALLBACK_TOKEN_SENT,
++ 1,
++ callback_expiry,
++ NULL);
++ my_token_callback_active = 1;
++ }
+ }
+
+ static void message_handler_req_exec_ckpt_checkpointclose (
+@@ -1593,8 +1607,10 @@
+ res_lib_ckpt_checkpointclose.header.size = sizeof (struct res_lib_ckpt_checkpointclose);
+ res_lib_ckpt_checkpointclose.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTCLOSE;
+ res_lib_ckpt_checkpointclose.header.error = error;
+- openais_conn_send_response (req_exec_ckpt_checkpointclose->source.conn,
+- &res_lib_ckpt_checkpointclose, sizeof (struct res_lib_ckpt_checkpointclose));
++ openais_response_send (
++ req_exec_ckpt_checkpointclose->source.conn,
++ &res_lib_ckpt_checkpointclose,
++ sizeof (struct res_lib_ckpt_checkpointclose));
+ }
+
+ /*
+@@ -1646,7 +1662,7 @@
+ res_lib_ckpt_checkpointunlink.header.size = sizeof (struct res_lib_ckpt_checkpointunlink);
+ res_lib_ckpt_checkpointunlink.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTUNLINK;
+ res_lib_ckpt_checkpointunlink.header.error = error;
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_checkpointunlink->source.conn,
+ &res_lib_ckpt_checkpointunlink,
+ sizeof (struct res_lib_ckpt_checkpointunlink));
+@@ -1694,7 +1710,7 @@
+ res_lib_ckpt_checkpointretentiondurationset.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTRETENTIONDURATIONSET;
+ res_lib_ckpt_checkpointretentiondurationset.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_checkpointretentiondurationset->source.conn,
+ &res_lib_ckpt_checkpointretentiondurationset,
+ sizeof (struct res_lib_ckpt_checkpointretentiondurationset));
+@@ -1900,7 +1916,8 @@
+ res_lib_ckpt_sectioncreate.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONCREATE;
+ res_lib_ckpt_sectioncreate.header.error = error;
+
+- openais_conn_send_response (req_exec_ckpt_sectioncreate->source.conn,
++ openais_response_send (
++ req_exec_ckpt_sectioncreate->source.conn,
+ &res_lib_ckpt_sectioncreate,
+ sizeof (struct res_lib_ckpt_sectioncreate));
+ }
+@@ -1965,7 +1982,7 @@
+ res_lib_ckpt_sectiondelete.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONDELETE;
+ res_lib_ckpt_sectiondelete.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_sectiondelete->source.conn,
+ &res_lib_ckpt_sectiondelete,
+ sizeof (struct res_lib_ckpt_sectiondelete));
+@@ -2058,7 +2075,7 @@
+ MESSAGE_RES_CKPT_CHECKPOINT_SECTIONEXPIRATIONTIMESET;
+ res_lib_ckpt_sectionexpirationtimeset.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_sectionexpirationtimeset->source.conn,
+ &res_lib_ckpt_sectionexpirationtimeset,
+ sizeof (struct res_lib_ckpt_sectionexpirationtimeset));
+@@ -2168,7 +2185,7 @@
+ MESSAGE_RES_CKPT_CHECKPOINT_SECTIONWRITE;
+ res_lib_ckpt_sectionwrite.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_sectionwrite->source.conn,
+ &res_lib_ckpt_sectionwrite,
+ sizeof (struct res_lib_ckpt_sectionwrite));
+@@ -2265,7 +2282,7 @@
+ MESSAGE_RES_CKPT_CHECKPOINT_SECTIONOVERWRITE;
+ res_lib_ckpt_sectionoverwrite.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_sectionoverwrite->source.conn,
+ &res_lib_ckpt_sectionoverwrite,
+ sizeof (struct res_lib_ckpt_sectionoverwrite));
+@@ -2358,7 +2375,7 @@
+ res_lib_ckpt_sectionread.data_read = section_size;
+ }
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_sectionread->source.conn,
+ &res_lib_ckpt_sectionread,
+ sizeof (struct res_lib_ckpt_sectionread));
+@@ -2369,7 +2386,7 @@
+ if (error == SA_AIS_OK) {
+ char *sd;
+ sd = (char *)checkpoint_section->section_data;
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_ckpt_sectionread->source.conn,
+ &sd[req_exec_ckpt_sectionread->data_offset],
+ section_size);
+@@ -2394,6 +2411,7 @@
+ struct checkpoint_cleanup *checkpoint_cleanup;
+ struct list_head *list;
+ struct ckpt_pd *ckpt_pd = (struct ckpt_pd *)openais_conn_private_data_get (conn);
++ unsigned int res;
+
+ log_printf (LOG_LEVEL_DEBUG, "checkpoint exit conn %p\n", conn);
+
+@@ -2407,9 +2425,16 @@
+ struct checkpoint_cleanup, list);
+
+ assert (checkpoint_cleanup->checkpoint_name.length != 0);
+- ckpt_checkpoint_close (
++ res = ckpt_checkpoint_close (
+ &checkpoint_cleanup->checkpoint_name,
+ checkpoint_cleanup->ckpt_id);
++ /*
++ * If checkpoint_close fails because of full totem queue
++ * return -1 ande try again later
++ */
++ if (res == -1) {
++ return (-1);
++ }
+
+ list_del (&checkpoint_cleanup->list);
+ free (checkpoint_cleanup);
+@@ -2578,7 +2603,7 @@
+ res_lib_ckpt_activereplicaset.header.id = MESSAGE_RES_CKPT_ACTIVEREPLICASET;
+ res_lib_ckpt_activereplicaset.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_activereplicaset,
+ sizeof (struct res_lib_ckpt_activereplicaset));
+@@ -2641,7 +2666,7 @@
+ res_lib_ckpt_checkpointstatusget.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSTATUSGET;
+ res_lib_ckpt_checkpointstatusget.header.error = SA_AIS_ERR_NOT_EXIST;
+ }
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_checkpointstatusget,
+ sizeof (struct res_lib_ckpt_checkpointstatusget));
+@@ -2655,8 +2680,6 @@
+ struct req_exec_ckpt_sectioncreate req_exec_ckpt_sectioncreate;
+ struct iovec iovecs[2];
+
+- log_printf (LOG_LEVEL_DEBUG, "Section create from conn %p\n", conn);
+-
+ req_exec_ckpt_sectioncreate.header.id =
+ SERVICE_ID_MAKE (CKPT_SERVICE,
+ MESSAGE_REQ_EXEC_CKPT_SECTIONCREATE);
+@@ -2692,7 +2715,6 @@
+ }
+
+ if (iovecs[1].iov_len > 0) {
+- log_printf (LOG_LEVEL_DEBUG, "IOV_BASE is %p\n", iovecs[1].iov_base);
+ assert (totempg_groups_mcast_joined (openais_group_handle, iovecs, 2, TOTEMPG_AGREED) == 0);
+ } else {
+ assert (totempg_groups_mcast_joined (openais_group_handle, iovecs, 1, TOTEMPG_AGREED) == 0);
+@@ -2967,7 +2989,7 @@
+ res_lib_ckpt_checkpointsynchronize.header.size = sizeof (struct res_lib_ckpt_checkpointsynchronize);
+ res_lib_ckpt_checkpointsynchronize.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZE;
+
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_checkpointsynchronize,
+ sizeof (struct res_lib_ckpt_checkpointsynchronize));
+@@ -2998,13 +3020,13 @@
+ res_lib_ckpt_checkpointsynchronizeasync.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZEASYNC;
+ res_lib_ckpt_checkpointsynchronizeasync.invocation = req_lib_ckpt_checkpointsynchronizeasync->invocation;
+
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_checkpointsynchronizeasync,
+ sizeof (struct res_lib_ckpt_checkpointsynchronizeasync));
+
+- openais_conn_send_response (
+- openais_conn_partner_get (conn),
++ openais_dispatch_send (
++ conn,
+ &res_lib_ckpt_checkpointsynchronizeasync,
+ sizeof (struct res_lib_ckpt_checkpointsynchronizeasync));
+ }
+@@ -3133,7 +3155,7 @@
+ res_lib_ckpt_sectioniterationinitialize.max_section_id_size =
+ checkpoint->checkpoint_creation_attributes.max_section_id_size;
+
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_sectioniterationinitialize,
+ sizeof (struct res_lib_ckpt_sectioniterationinitialize));
+@@ -3174,7 +3196,7 @@
+ res_lib_ckpt_sectioniterationfinalize.header.id = MESSAGE_RES_CKPT_SECTIONITERATIONFINALIZE;
+ res_lib_ckpt_sectioniterationfinalize.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_sectioniterationfinalize,
+ sizeof (struct res_lib_ckpt_sectioniterationfinalize));
+@@ -3262,13 +3284,13 @@
+ res_lib_ckpt_sectioniterationnext.header.id = MESSAGE_RES_CKPT_SECTIONITERATIONNEXT;
+ res_lib_ckpt_sectioniterationnext.header.error = error;
+
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ &res_lib_ckpt_sectioniterationnext,
+ sizeof (struct res_lib_ckpt_sectioniterationnext));
+
+ if (error == SA_AIS_OK) {
+- openais_conn_send_response (
++ openais_response_send (
+ conn,
+ checkpoint_section->section_descriptor.section_id.id,
+ checkpoint_section->section_descriptor.section_id.id_len);
+@@ -3366,19 +3388,29 @@
+ list_init (ckpt_list_head);
+ }
+
+-static inline void sync_checkpoints_enter (void)
++static inline void sync_gloalid_enter (void)
+ {
+ struct checkpoint *checkpoint;
+
+ ENTER();
+
+- my_sync_state = SYNC_STATE_CHECKPOINT;
+- my_iteration_state = ITERATION_STATE_CHECKPOINT;
+- my_iteration_state_checkpoint = checkpoint_list_head.next;
++ my_sync_state = SYNC_STATE_GLOBALID;
++
++ my_iteration_state_checkpoint_list = checkpoint_list_head.next;
+
+ checkpoint = list_entry (checkpoint_list_head.next, struct checkpoint,
+ list);
+- my_iteration_state_section = checkpoint->sections_list_head.next;
++ my_iteration_state_section_list = checkpoint->sections_list_head.next;
++
++ LEAVE();
++}
++
++static inline void sync_checkpoints_enter (void)
++{
++ ENTER();
++
++ my_sync_state = SYNC_STATE_CHECKPOINT;
++ my_iteration_state = ITERATION_STATE_CHECKPOINT;
+
+ LEAVE();
+ }
+@@ -3386,13 +3418,15 @@
+ static inline void sync_refcounts_enter (void)
+ {
+ my_sync_state = SYNC_STATE_REFCOUNT;
++
++ my_iteration_state_checkpoint_list = checkpoint_list_head.next;
+ }
+
+ static void ckpt_sync_init (void)
+ {
+ ENTER();
+
+- sync_checkpoints_enter();
++ sync_gloalid_enter();
+
+ LEAVE();
+ }
+@@ -3432,6 +3466,19 @@
+ return (totempg_groups_mcast_joined (openais_group_handle, &iovec, 1, TOTEMPG_AGREED));
+ }
+
++static int sync_checkpoint_globalid_transmit (void)
++{
++ struct checkpoint checkpoint;
++
++ strcpy ((char *)checkpoint.name.value, GLOBALID_CHECKPOINT_NAME);
++
++ checkpoint.name.length = strlen (GLOBALID_CHECKPOINT_NAME);
++ checkpoint.ckpt_id = global_ckpt_id;
++
++ return (sync_checkpoint_transmit(&checkpoint));
++}
++
++
+ static int sync_checkpoint_section_transmit (
+ struct checkpoint *checkpoint,
+ struct checkpoint_section *checkpoint_section)
+@@ -3521,25 +3568,62 @@
+ struct list_head *section_list;
+ unsigned int res = 0;
+
+- for (checkpoint_list = checkpoint_list_head.next;
++ /*
++ * iterate through all checkpoints or sections
++ * from the last successfully transmitted checkpoint or sectoin
++ */
++ for (checkpoint_list = my_iteration_state_checkpoint_list;
+ checkpoint_list != &checkpoint_list_head;
+ checkpoint_list = checkpoint_list->next) {
+
+ checkpoint = list_entry (checkpoint_list, struct checkpoint, list);
+
+- res = sync_checkpoint_transmit (checkpoint);
+- if (res != 0) {
+- break;
++ /*
++ * Synchronize a checkpoint if there is room in the totem
++ * buffers and we didn't previously synchronize a checkpoint
++ */
++ if (my_iteration_state == ITERATION_STATE_CHECKPOINT) {
++ res = sync_checkpoint_transmit (checkpoint);
++ if (res != 0) {
++ /*
++ * Couldn't sync this checkpoint keep processing
++ */
++ return (-1);
++ }
++ my_iteration_state_section_list = checkpoint->sections_list_head.next;
++ my_iteration_state = ITERATION_STATE_SECTION;
+ }
+- for (section_list = checkpoint->sections_list_head.next;
++
++ /*
++ * Synchronize a checkpoint section if there is room in the
++ * totem buffers
++ */
++ for (section_list = my_iteration_state_section_list;
+ section_list != &checkpoint->sections_list_head;
+ section_list = section_list->next) {
+
+ checkpoint_section = list_entry (section_list, struct checkpoint_section, list);
+ res = sync_checkpoint_section_transmit (checkpoint, checkpoint_section);
++ if (res != 0) {
++ /*
++ * Couldn't sync this section keep processing
++ */
++ return (-1);
++ }
++ my_iteration_state_section_list = section_list->next;
+ }
++
++ /*
++ * Continue to iterating checkpoints
++ */
++ my_iteration_state = ITERATION_STATE_CHECKPOINT;
++ my_iteration_state_checkpoint_list = checkpoint_list->next;
+ }
+- return (res);
++
++ /*
++ * all checkpoints and sections iterated
++ */
++ return (0);
+ }
+
+ unsigned int sync_refcounts_iterate (void)
+@@ -3548,7 +3632,7 @@
+ struct list_head *list;
+ unsigned int res = 0;
+
+- for (list = checkpoint_list_head.next;
++ for (list = my_iteration_state_checkpoint_list;
+ list != &checkpoint_list_head;
+ list = list->next) {
+
+@@ -3558,48 +3642,68 @@
+ if (res != 0) {
+ break;
+ }
++ my_iteration_state_checkpoint_list = list->next;
+ }
+ return (res);
+ }
+
+ static int ckpt_sync_process (void)
+ {
+- unsigned int done_queueing = 1;
+- unsigned int continue_processing = 0;
++ unsigned int done_queueing;
++ unsigned int continue_processing;
+ unsigned int res;
+
+ ENTER();
+
++ continue_processing = 0;
++
+ switch (my_sync_state) {
++ case SYNC_STATE_GLOBALID:
++ done_queueing = 1;
++ continue_processing = 1;
++ if (my_should_sync) {
++ res = sync_checkpoint_globalid_transmit ();
++ if (res != 0) {
++ done_queueing = 0;
++ }
++ }
++ if (done_queueing) {
++ sync_checkpoints_enter ();
++ }
++ break;
++
+ case SYNC_STATE_CHECKPOINT:
+- if (my_lowest_nodeid == this_ip->nodeid) {
++ done_queueing = 1;
++ continue_processing = 1;
++
++ if (my_should_sync) {
+ TRACE1 ("should transmit checkpoints because lowest member in old configuration.\n");
+ res = sync_checkpoints_iterate ();
+
+- if (res == 0) {
+- done_queueing = 1;
++ /*
++ * Not done iterating checkpoints
++ */
++ if (res != 0) {
++ done_queueing = 0;
+ }
+ }
+ if (done_queueing) {
+ sync_refcounts_enter ();
+ }
+-
+- /*
+- * TODO recover current iteration state
+- */
+- continue_processing = 1;
+ break;
+
+ case SYNC_STATE_REFCOUNT:
+- done_queueing = 1;
+- if (my_lowest_nodeid == this_ip->nodeid) {
++ if (my_should_sync) {
+ TRACE1 ("transmit refcounts because this processor is the lowest member in old configuration.\n");
+ res = sync_refcounts_iterate ();
+- }
+- if (done_queueing) {
+- continue_processing = 0;
++ if (res != 0) {
++ continue_processing = 1;
++ }
+ }
+ break;
++
++ default:
++ assert (0);
+ }
+
+ LEAVE();
+@@ -3620,7 +3724,7 @@
+
+ list_init (&sync_checkpoint_list_head);
+
+- my_sync_state = SYNC_STATE_CHECKPOINT;
++ my_sync_state = SYNC_STATE_NOT_STARTED;
+
+ LEAVE();
+ }
+@@ -3648,6 +3752,22 @@
+ return;
+ }
+
++ /*
++ * Discard checkpoints that are used to synchronize the global_ckpt_id
++ * also setting the global ckpt_id as well.
++ */
++ if (memcmp (&req_exec_ckpt_sync_checkpoint->checkpoint_name.value,
++ GLOBALID_CHECKPOINT_NAME,
++ req_exec_ckpt_sync_checkpoint->checkpoint_name.length) == 0) {
++
++ if (req_exec_ckpt_sync_checkpoint->ckpt_id >= global_ckpt_id) {
++ global_ckpt_id = req_exec_ckpt_sync_checkpoint->ckpt_id + 1;
++ }
++
++ LEAVE();
++ return;
++ }
++
+ checkpoint = checkpoint_find_specific (
+ &sync_checkpoint_list_head,
+ &req_exec_ckpt_sync_checkpoint->checkpoint_name,
+diff -uNr openais-0.80.3/exec/clm.c openais-0.80.3-r1661/exec/clm.c
+--- openais-0.80.3/exec/clm.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/clm.c 2008-11-17 15:54:02.380604445 +0100
+@@ -262,24 +262,29 @@
+ mar_clm_cluster_node_t cluster_node __attribute__((aligned(8)));
+ };
+
+-static int clm_exec_init_fn (struct objdb_iface_ver0 *objdb)
++static void my_cluster_node_load (void)
+ {
+- log_init ("CLM");
++ struct totem_ip_address interfaces[INTERFACE_MAX];
++ unsigned int iface_count;
++ char **status;
++ const char *iface_string;
++
++ totempg_ifaces_get (
++ totempg_my_nodeid_get (),
++ interfaces,
++ &status,
++ &iface_count);
+
+- memset (cluster_node_entries, 0,
+- sizeof (mar_clm_cluster_node_t) * PROCESSOR_COUNT_MAX);
++ iface_string = totemip_print (&interfaces[0]);
+
+- /*
+- * Build local cluster node data structure
+- */
+ sprintf ((char *)my_cluster_node.node_address.value, "%s",
+- totemip_print (this_ip));
++ iface_string);
+ my_cluster_node.node_address.length =
+ strlen ((char *)my_cluster_node.node_address.value);
+- if (this_ip->family == AF_INET) {
++ if (totempg_my_family_get () == AF_INET) {
+ my_cluster_node.node_address.family = SA_CLM_AF_INET;
+ } else
+- if (this_ip->family == AF_INET6) {
++ if (totempg_my_family_get () == AF_INET6) {
+ my_cluster_node.node_address.family = SA_CLM_AF_INET6;
+ } else {
+ assert (0);
+@@ -289,8 +294,20 @@
+ (char *)my_cluster_node.node_address.value);
+ my_cluster_node.node_name.length =
+ my_cluster_node.node_address.length;
+- my_cluster_node.node_id = this_ip->nodeid;
++ my_cluster_node.node_id = totempg_my_nodeid_get ();
+ my_cluster_node.member = 1;
++
++ memcpy (&cluster_node_entries[0], &my_cluster_node,
++ sizeof (mar_clm_cluster_node_t));
++}
++
++static int clm_exec_init_fn (struct objdb_iface_ver0 *objdb)
++{
++ log_init ("CLM");
++
++ memset (cluster_node_entries, 0,
++ sizeof (mar_clm_cluster_node_t) * PROCESSOR_COUNT_MAX);
++
+ {
+ #if defined(OPENAIS_LINUX)
+ struct sysinfo s_info;
+@@ -313,7 +330,6 @@
+ #endif
+ }
+
+- memcpy (&cluster_node_entries[0], &my_cluster_node, sizeof (mar_clm_cluster_node_t));
+ cluster_node_count = 1;
+
+ main_clm_get_by_nodeid = clm_get_by_nodeid;
+@@ -391,7 +407,7 @@
+ /*
+ * Send notifications to all CLM listeners
+ */
+- openais_conn_send_response (
++ openais_dispatch_send (
+ clm_pd->conn,
+ &res_lib_clm_clustertrack,
+ sizeof (struct res_lib_clm_clustertrack));
+@@ -519,20 +535,7 @@
+ * Load the my_cluster_node data structure in case we are
+ * transitioning to network interface up or down
+ */
+- sprintf ((char *)my_cluster_node.node_address.value, "%s", totemip_print (this_ip));
+- my_cluster_node.node_address.length = strlen ((char *)my_cluster_node.node_address.value);
+- if (this_ip->family == AF_INET) {
+- my_cluster_node.node_address.family = SA_CLM_AF_INET;
+- } else
+- if (this_ip->family == AF_INET6) {
+- my_cluster_node.node_address.family = SA_CLM_AF_INET6;
+- } else {
+- assert (0);
+- }
+- strcpy ((char *)my_cluster_node.node_name.value,
+- (char *)my_cluster_node.node_address.value);
+- my_cluster_node.node_name.length = my_cluster_node.node_address.length;
+- my_cluster_node.node_id = this_ip->nodeid;
++ my_cluster_node_load ();
+ }
+
+ /*
+@@ -664,14 +667,16 @@
+ list_add (&clm_pd->list, &library_notification_send_listhead);
+ }
+
+- openais_conn_send_response (conn, &res_lib_clm_clustertrack,
++ openais_response_send (
++ conn,
++ &res_lib_clm_clustertrack,
+ sizeof (struct res_lib_clm_clustertrack));
+
+ if (req_lib_clm_clustertrack->return_in_callback) {
+ res_lib_clm_clustertrack.header.id = MESSAGE_RES_CLM_TRACKCALLBACK;
+
+- openais_conn_send_response (
+- openais_conn_partner_get (conn),
++ openais_dispatch_send (
++ conn,
+ &res_lib_clm_clustertrack,
+ sizeof (struct res_lib_clm_clustertrack));
+ }
+@@ -696,7 +701,9 @@
+ list_del (&clm_pd->list);
+ list_init (&clm_pd->list);
+
+- openais_conn_send_response (conn, &res_lib_clm_trackstop,
++ openais_response_send (
++ conn,
++ &res_lib_clm_trackstop,
+ sizeof (struct res_lib_clm_trackstop));
+ }
+
+@@ -732,7 +739,11 @@
+ if (valid) {
+ memcpy (&res_clm_nodeget.cluster_node, cluster_node, sizeof (mar_clm_cluster_node_t));
+ }
+- openais_conn_send_response (conn, &res_clm_nodeget, sizeof (struct res_clm_nodeget));
++
++ openais_response_send (
++ conn,
++ &res_clm_nodeget,
++ sizeof (struct res_clm_nodeget));
+ }
+
+ static void message_handler_req_lib_clm_nodegetasync (void *conn, void *msg)
+@@ -767,7 +778,9 @@
+ res_clm_nodegetasync.header.id = MESSAGE_RES_CLM_NODEGETASYNC;
+ res_clm_nodegetasync.header.error = SA_AIS_OK;
+
+- openais_conn_send_response (conn, &res_clm_nodegetasync,
++ openais_response_send (
++ conn,
++ &res_clm_nodegetasync,
+ sizeof (struct res_clm_nodegetasync));
+
+ /*
+@@ -781,7 +794,8 @@
+ memcpy (&res_clm_nodegetcallback.cluster_node, cluster_node,
+ sizeof (mar_clm_cluster_node_t));
+ }
+- openais_conn_send_response (openais_conn_partner_get (conn),
++ openais_dispatch_send (
++ conn,
+ &res_clm_nodegetcallback,
+ sizeof (struct res_clm_nodegetcallback));
+ }
+diff -uNr openais-0.80.3/exec/cpg.c openais-0.80.3-r1661/exec/cpg.c
+--- openais-0.80.3/exec/cpg.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/cpg.c 2008-11-17 15:54:02.380604445 +0100
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2006-2007 Red Hat, Inc.
++ * Copyright (c) 2006 Red Hat, Inc.
+ * Copyright (c) 2006 Sun Microsystems, Inc.
+ *
+ * All rights reserved.
+@@ -32,6 +32,9 @@
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
++#ifndef OPENAIS_BSD
++#include <alloca.h>
++#endif
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
+@@ -60,8 +63,11 @@
+ #include "totempg.h"
+ #include "totemip.h"
+ #include "main.h"
++#include "flow.h"
++#include "tlist.h"
+ #include "ipc.h"
+ #include "mempool.h"
++#include "objdb.h"
+ #include "service.h"
+ #include "jhash.h"
+ #include "swab.h"
+@@ -255,7 +261,7 @@
+ };
+
+ struct openais_service_handler cpg_service_handler = {
+- .name = (unsigned char*)"openais cluster closed process group service v1.01",
++ .name = (unsigned char *)"openais cluster closed process group service v1.01",
+ .id = CPG_SERVICE,
+ .private_data_size = sizeof (struct process_info),
+ .flow_control = OPENAIS_FLOW_CONTROL_REQUIRED,
+@@ -434,14 +440,14 @@
+ }
+
+ if (conn) {
+- openais_conn_send_response(conn, buf, size);
++ openais_dispatch_send(conn, buf, size);
+ }
+ else {
+ /* Send it to all listeners */
+ for (iter = gi->members.next, tmp=iter->next; iter != &gi->members; iter = tmp, tmp=iter->next) {
+ struct process_info *pi = list_entry(iter, struct process_info, list);
+ if (pi->trackerconn && (pi->flags & PI_FLAG_MEMBER)) {
+- if (openais_conn_send_response(pi->trackerconn, buf, size) == -1) {
++ if (openais_dispatch_send(pi->trackerconn, buf, size) == -1) {
+ // Error ??
+ }
+ }
+@@ -477,14 +483,17 @@
+ struct group_info *gi = pi->group;
+ mar_cpg_address_t notify_info;
+
+- log_printf(LOG_LEVEL_DEBUG, "exit_fn for conn=%p\n", conn);
+-
+ if (gi) {
+ notify_info.pid = pi->pid;
+- notify_info.nodeid = this_ip->nodeid;
++ notify_info.nodeid = totempg_my_nodeid_get();
+ notify_info.reason = CONFCHG_CPG_REASON_PROCDOWN;
+ cpg_node_joinleave_send(gi, pi, MESSAGE_REQ_EXEC_CPG_PROCLEAVE, CONFCHG_CPG_REASON_PROCDOWN);
+ list_del(&pi->list);
++ openais_ipc_flow_control_destroy (
++ conn,
++ CPG_SERVICE,
++ (unsigned char *)gi->group_name.value,
++ (unsigned int)gi->group_name.length);
+ }
+ return (0);
+ }
+@@ -531,7 +540,7 @@
+ req_exec_cpg_procjoin.header.size = sizeof(req_exec_cpg_procjoin);
+ req_exec_cpg_procjoin.header.id = SERVICE_ID_MAKE(CPG_SERVICE, fn);
+
+- req_exec_cpg_iovec.iov_base = &req_exec_cpg_procjoin;
++ req_exec_cpg_iovec.iov_base = (char *)&req_exec_cpg_procjoin;
+ req_exec_cpg_iovec.iov_len = sizeof(req_exec_cpg_procjoin);
+
+ result = totempg_groups_mcast_joined (openais_group_handle, &req_exec_cpg_iovec, 1, TOTEMPG_AGREED);
+@@ -544,15 +553,17 @@
+ struct list_head *remlist)
+ {
+ int i;
+- struct list_head *iter, *iter2, *tmp;
++ struct list_head *iter, *iter2;
+ struct process_info *pi;
+ struct group_info *gi;
+
+ for (i=0; i < GROUP_HASH_SIZE; i++) {
+- for (iter = group_lists[i].next; iter != &group_lists[i]; iter = iter->next) {
++ for (iter = group_lists[i].next; iter != &group_lists[i];) {
+ gi = list_entry(iter, struct group_info, list);
+- for (iter2 = gi->members.next, tmp = iter2->next; iter2 != &gi->members; iter2 = tmp, tmp = iter2->next) {
++ iter = iter->next;
++ for (iter2 = gi->members.next; iter2 != &gi->members;) {
+ pi = list_entry(iter2, struct process_info, list);
++ iter2 = iter2->next;
+
+ if (pi->nodeid == nodeid) {
+
+@@ -627,8 +638,8 @@
+ lowest_nodeid = member_list[i];
+ }
+
+- log_printf(LOG_LEVEL_DEBUG, "confchg, low nodeid=%d, us = %d\n", lowest_nodeid, this_ip->nodeid);
+- if (lowest_nodeid == this_ip->nodeid) {
++ log_printf(LOG_LEVEL_DEBUG, "confchg, low nodeid=%d, us = %d\n", lowest_nodeid, totempg_my_nodeid_get());
++ if (lowest_nodeid == totempg_my_nodeid_get()) {
+
+ req_exec_cpg_downlist.header.id = SERVICE_ID_MAKE(CPG_SERVICE, MESSAGE_REQ_EXEC_CPG_DOWNLIST);
+ req_exec_cpg_downlist.header.size = sizeof(struct req_exec_cpg_downlist);
+@@ -643,7 +654,7 @@
+
+ /* Don't send this message until we get the final configuration message */
+ if (configuration_type == TOTEM_CONFIGURATION_REGULAR && req_exec_cpg_downlist.left_nodes) {
+- req_exec_cpg_iovec.iov_base = &req_exec_cpg_downlist;
++ req_exec_cpg_iovec.iov_base = (char *)&req_exec_cpg_downlist;
+ req_exec_cpg_iovec.iov_len = req_exec_cpg_downlist.header.size;
+
+ totempg_groups_mcast_joined (openais_group_handle, &req_exec_cpg_iovec, 1, TOTEMPG_AGREED);
+@@ -688,10 +699,16 @@
+ static void exec_cpg_downlist_endian_convert (void *msg)
+ {
+ struct req_exec_cpg_downlist *req_exec_cpg_downlist = (struct req_exec_cpg_downlist *)msg;
++ unsigned int i;
+
+ req_exec_cpg_downlist->left_nodes = swab32(req_exec_cpg_downlist->left_nodes);
++
++ for (i = 0; i < req_exec_cpg_downlist->left_nodes; i++) {
++ req_exec_cpg_downlist->nodeids[i] = swab32(req_exec_cpg_downlist->nodeids[i]);
++ }
+ }
+
++
+ static void exec_cpg_mcast_endian_convert (void *msg)
+ {
+ struct req_exec_cpg_mcast *req_exec_cpg_mcast = (struct req_exec_cpg_mcast *)msg;
+@@ -723,7 +740,7 @@
+ if (pi->pid == pid && pi->nodeid == nodeid) {
+
+ /* It could be a local join message */
+- if ((nodeid == this_ip->nodeid) &&
++ if ((nodeid == totempg_my_nodeid_get()) &&
+ (!pi->flags & PI_FLAG_MEMBER)) {
+ goto local_join;
+ } else {
+@@ -810,7 +827,7 @@
+ struct req_exec_cpg_procjoin *req_exec_cpg_procjoin = (struct req_exec_cpg_procjoin *)message;
+ struct group_info *gi;
+ struct process_info *pi;
+- struct list_head *iter;
++ volatile struct list_head *iter;
+ mar_cpg_address_t notify_info;
+
+ log_printf(LOG_LEVEL_DEBUG, "got procleave message from cluster node %d\n", nodeid);
+@@ -827,19 +844,28 @@
+ 1, &notify_info,
+ MESSAGE_RES_CPG_CONFCHG_CALLBACK);
+
+- /* Find the node/PID to remove */
+- for (iter = gi->members.next; iter != &gi->members; iter = iter->next) {
++ /*
++ * Find the node/PID to remove
++ */
++ for (iter = gi->members.next; iter != &gi->members;) {
+ pi = list_entry(iter, struct process_info, list);
++
++ iter = iter->next;
++
+ if (pi->pid == req_exec_cpg_procjoin->pid &&
+ pi->nodeid == nodeid) {
+
+- list_del(&pi->list);
+- if (!pi->conn)
+- free(pi);
+-
+ if (list_empty(&gi->members)) {
+ remove_group(gi);
+ }
++
++ list_del(&pi->list);
++ if (pi->conn) {
++ openais_conn_info_refcnt_dec(pi->conn);
++ } else {
++ free(pi);
++ }
++
+ break;
+ }
+ }
+@@ -858,7 +884,7 @@
+ nodeid);
+
+ /* Ignore our own messages */
+- if (nodeid == this_ip->nodeid) {
++ if (nodeid == totempg_my_nodeid_get()) {
+ return;
+ }
+
+@@ -898,6 +924,7 @@
+ openais_ipc_flow_control_local_decrement (req_exec_cpg_mcast->source.conn);
+ process_info = (struct process_info *)openais_conn_private_data_get (req_exec_cpg_mcast->source.conn);
+ res_lib_cpg_mcast->flow_control_state = process_info->flow_control_state;
++ openais_conn_info_refcnt_dec (req_exec_cpg_mcast->source.conn);
+ }
+ memcpy(&res_lib_cpg_mcast->group_name, &gi->group_name,
+ sizeof(mar_cpg_name_t));
+@@ -907,8 +934,8 @@
+ /* Send to all interested members */
+ for (iter = gi->members.next; iter != &gi->members; iter = iter->next) {
+ struct process_info *pi = list_entry(iter, struct process_info, list);
+- if (pi->trackerconn) {
+- openais_conn_send_response(
++ if (pi->trackerconn && (pi->flags & PI_FLAG_MEMBER)) {
++ openais_dispatch_send (
+ pi->trackerconn,
+ buf,
+ res_lib_cpg_mcast->header.size);
+@@ -937,7 +964,7 @@
+ gi = list_entry(iter, struct group_info, list);
+ for (iter2 = gi->members.next; iter2 != &gi->members; iter2 = iter2->next) {
+ struct process_info *pi = list_entry(iter2, struct process_info, list);
+- if (pi->pid && pi->nodeid == this_ip->nodeid) {
++ if (pi->pid && pi->nodeid == totempg_my_nodeid_get()) {
+ count++;
+ }
+ }
+@@ -964,7 +991,7 @@
+ for (iter2 = gi->members.next; iter2 != &gi->members; iter2 = iter2->next) {
+
+ struct process_info *pi = list_entry(iter2, struct process_info, list);
+- if (pi->pid && pi->nodeid == this_ip->nodeid) {
++ if (pi->pid && pi->nodeid == totempg_my_nodeid_get()) {
+ memcpy(&jle->group_name, &gi->group_name, sizeof(mar_cpg_name_t));
+ jle->pid = pi->pid;
+ jle++;
+@@ -987,6 +1014,7 @@
+ struct process_info *pi = (struct process_info *)openais_conn_private_data_get (conn);
+ pi->conn = conn;
+
++ openais_conn_info_refcnt_inc (conn);
+ log_printf(LOG_LEVEL_DEBUG, "lib_init_fn: conn=%p, pi=%p\n", conn, pi);
+ return (0);
+ }
+@@ -1023,7 +1051,7 @@
+ pi);
+
+ /* Add a node entry for us */
+- pi->nodeid = this_ip->nodeid;
++ pi->nodeid = totempg_my_nodeid_get();
+ pi->pid = req_lib_cpg_join->pid;
+ pi->group = gi;
+ list_add(&pi->list, &gi->members);
+@@ -1035,7 +1063,7 @@
+ res_lib_cpg_join.header.size = sizeof(res_lib_cpg_join);
+ res_lib_cpg_join.header.id = MESSAGE_RES_CPG_JOIN;
+ res_lib_cpg_join.header.error = error;
+- openais_conn_send_response(conn, &res_lib_cpg_join, sizeof(res_lib_cpg_join));
++ openais_response_send(conn, &res_lib_cpg_join, sizeof(res_lib_cpg_join));
+ }
+
+ /* Leave message from the library */
+@@ -1046,8 +1074,6 @@
+ struct group_info *gi;
+ SaAisErrorT error = SA_AIS_OK;
+
+- log_printf(LOG_LEVEL_DEBUG, "got leave request on %p\n", conn);
+-
+ if (!pi || !pi->pid || !pi->group) {
+ error = SA_AIS_ERR_INVALID_PARAM;
+ goto leave_ret;
+@@ -1070,7 +1096,7 @@
+ res_lib_cpg_leave.header.size = sizeof(res_lib_cpg_leave);
+ res_lib_cpg_leave.header.id = MESSAGE_RES_CPG_LEAVE;
+ res_lib_cpg_leave.header.error = error;
+- openais_conn_send_response(conn, &res_lib_cpg_leave, sizeof(res_lib_cpg_leave));
++ openais_response_send(conn, &res_lib_cpg_leave, sizeof(res_lib_cpg_leave));
+ }
+
+ /* Mcast message from the library */
+@@ -1093,7 +1119,7 @@
+ res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST;
+ res_lib_cpg_mcast.header.error = SA_AIS_ERR_ACCESS; /* TODO Better error code ?? */
+ res_lib_cpg_mcast.flow_control_state = CPG_FLOW_CONTROL_DISABLED;
+- openais_conn_send_response(conn, &res_lib_cpg_mcast,
++ openais_response_send(conn, &res_lib_cpg_mcast,
+ sizeof(res_lib_cpg_mcast));
+ return;
+ }
+@@ -1101,15 +1127,16 @@
+ req_exec_cpg_mcast.header.size = sizeof(req_exec_cpg_mcast) + msglen;
+ req_exec_cpg_mcast.header.id = SERVICE_ID_MAKE(CPG_SERVICE,
+ MESSAGE_REQ_EXEC_CPG_MCAST);
++ openais_conn_info_refcnt_inc (conn);
+ req_exec_cpg_mcast.pid = pi->pid;
+ req_exec_cpg_mcast.msglen = msglen;
+ message_source_set (&req_exec_cpg_mcast.source, conn);
+ memcpy(&req_exec_cpg_mcast.group_name, &gi->group_name,
+ sizeof(mar_cpg_name_t));
+
+- req_exec_cpg_iovec[0].iov_base = &req_exec_cpg_mcast;
++ req_exec_cpg_iovec[0].iov_base = (char *)&req_exec_cpg_mcast;
+ req_exec_cpg_iovec[0].iov_len = sizeof(req_exec_cpg_mcast);
+- req_exec_cpg_iovec[1].iov_base = &req_lib_cpg_mcast->message;
++ req_exec_cpg_iovec[1].iov_base = (char *)&req_lib_cpg_mcast->message;
+ req_exec_cpg_iovec[1].iov_len = msglen;
+
+ // TODO: guarantee type...
+@@ -1120,7 +1147,7 @@
+ res_lib_cpg_mcast.header.id = MESSAGE_RES_CPG_MCAST;
+ res_lib_cpg_mcast.header.error = SA_AIS_OK;
+ res_lib_cpg_mcast.flow_control_state = pi->flow_control_state;
+- openais_conn_send_response(conn, &res_lib_cpg_mcast,
++ openais_response_send(conn, &res_lib_cpg_mcast,
+ sizeof(res_lib_cpg_mcast));
+ }
+
+@@ -1134,7 +1161,7 @@
+ res.size = sizeof(res);
+ res.id = MESSAGE_RES_CPG_MEMBERSHIP;
+ res.error = SA_AIS_ERR_ACCESS; /* TODO Better error code */
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ return;
+ }
+
+@@ -1148,7 +1175,6 @@
+ struct res_lib_cpg_trackstart res_lib_cpg_trackstart;
+ struct group_info *gi;
+ struct process_info *otherpi;
+- void *otherconn;
+ SaAisErrorT error = SA_AIS_OK;
+
+ log_printf(LOG_LEVEL_DEBUG, "got trackstart request on %p\n", conn);
+@@ -1160,7 +1186,6 @@
+ }
+
+ /* Find the partner connection and add us to it's process_info struct */
+- otherconn = openais_conn_partner_get (conn);
+ otherpi = (struct process_info *)openais_conn_private_data_get (conn);
+ otherpi->trackerconn = conn;
+
+@@ -1168,7 +1193,7 @@
+ res_lib_cpg_trackstart.header.size = sizeof(res_lib_cpg_trackstart);
+ res_lib_cpg_trackstart.header.id = MESSAGE_RES_CPG_TRACKSTART;
+ res_lib_cpg_trackstart.header.error = SA_AIS_OK;
+- openais_conn_send_response(conn, &res_lib_cpg_trackstart, sizeof(res_lib_cpg_trackstart));
++ openais_response_send(conn, &res_lib_cpg_trackstart, sizeof(res_lib_cpg_trackstart));
+ }
+
+ static void message_handler_req_lib_cpg_trackstop (void *conn, void *message)
+@@ -1176,7 +1201,6 @@
+ struct req_lib_cpg_trackstop *req_lib_cpg_trackstop = (struct req_lib_cpg_trackstop *)message;
+ struct res_lib_cpg_trackstop res_lib_cpg_trackstop;
+ struct process_info *otherpi;
+- void *otherconn;
+ struct group_info *gi;
+ SaAisErrorT error = SA_AIS_OK;
+
+@@ -1189,7 +1213,6 @@
+ }
+
+ /* Find the partner connection and add us to it's process_info struct */
+- otherconn = openais_conn_partner_get (conn);
+ otherpi = (struct process_info *)openais_conn_private_data_get (conn);
+ otherpi->trackerconn = NULL;
+
+@@ -1197,7 +1220,7 @@
+ res_lib_cpg_trackstop.header.size = sizeof(res_lib_cpg_trackstop);
+ res_lib_cpg_trackstop.header.id = MESSAGE_RES_CPG_TRACKSTOP;
+ res_lib_cpg_trackstop.header.error = SA_AIS_OK;
+- openais_conn_send_response(conn, &res_lib_cpg_trackstop.header, sizeof(res_lib_cpg_trackstop));
++ openais_response_send(conn, &res_lib_cpg_trackstop.header, sizeof(res_lib_cpg_trackstop));
+ }
+
+ static void message_handler_req_lib_cpg_local_get (void *conn, void *message)
+@@ -1207,8 +1230,8 @@
+ res_lib_cpg_local_get.header.size = sizeof(res_lib_cpg_local_get);
+ res_lib_cpg_local_get.header.id = MESSAGE_RES_CPG_LOCAL_GET;
+ res_lib_cpg_local_get.header.error = SA_AIS_OK;
+- res_lib_cpg_local_get.local_nodeid = this_ip->nodeid;
++ res_lib_cpg_local_get.local_nodeid = totempg_my_nodeid_get ();
+
+- openais_conn_send_response(conn, &res_lib_cpg_local_get,
++ openais_response_send(conn, &res_lib_cpg_local_get,
+ sizeof(res_lib_cpg_local_get));
+ }
+diff -uNr openais-0.80.3/exec/evs.c openais-0.80.3-r1661/exec/evs.c
+--- openais-0.80.3/exec/evs.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/evs.c 2008-11-17 15:54:02.380604445 +0100
+@@ -244,7 +244,8 @@
+ */
+ for (list = confchg_notify.next; list != &confchg_notify; list = list->next) {
+ evs_pd = list_entry (list, struct evs_pd, list);
+- openais_conn_send_response (evs_pd->conn,
++ openais_dispatch_send (
++ evs_pd->conn,
+ &res_evs_confchg_callback,
+ sizeof (res_evs_confchg_callback));
+ }
+@@ -262,7 +263,9 @@
+ list_init (&evs_pd->list);
+ list_add (&evs_pd->list, &confchg_notify);
+
+- openais_conn_send_response (conn, &res_evs_confchg_callback,
++ openais_dispatch_send (
++ conn,
++ &res_evs_confchg_callback,
+ sizeof (res_evs_confchg_callback));
+
+ return (0);
+@@ -308,7 +311,9 @@
+ res_lib_evs_join.header.id = MESSAGE_RES_EVS_JOIN;
+ res_lib_evs_join.header.error = error;
+
+- openais_conn_send_response (conn, &res_lib_evs_join,
++ openais_response_send (
++ conn,
++ &res_lib_evs_join,
+ sizeof (struct res_lib_evs_join));
+ }
+
+@@ -354,7 +359,9 @@
+ res_lib_evs_leave.header.id = MESSAGE_RES_EVS_LEAVE;
+ res_lib_evs_leave.header.error = error;
+
+- openais_conn_send_response (conn, &res_lib_evs_leave,
++ openais_response_send (
++ conn,
++ &res_lib_evs_leave,
+ sizeof (struct res_lib_evs_leave));
+ }
+
+@@ -397,7 +404,9 @@
+ res_lib_evs_mcast_joined.header.id = MESSAGE_RES_EVS_MCAST_JOINED;
+ res_lib_evs_mcast_joined.header.error = error;
+
+- openais_conn_send_response (conn, &res_lib_evs_mcast_joined,
++ openais_response_send (
++ conn,
++ &res_lib_evs_mcast_joined,
+ sizeof (struct res_lib_evs_mcast_joined));
+ }
+
+@@ -443,7 +452,9 @@
+ res_lib_evs_mcast_groups.header.id = MESSAGE_RES_EVS_MCAST_GROUPS;
+ res_lib_evs_mcast_groups.header.error = error;
+
+- openais_conn_send_response (conn, &res_lib_evs_mcast_groups,
++ openais_response_send (
++ conn,
++ &res_lib_evs_mcast_groups,
+ sizeof (struct res_lib_evs_mcast_groups));
+ }
+
+@@ -454,7 +465,7 @@
+ res_lib_evs_membership_get.header.size = sizeof (struct res_lib_evs_membership_get);
+ res_lib_evs_membership_get.header.id = MESSAGE_RES_EVS_MEMBERSHIP_GET;
+ res_lib_evs_membership_get.header.error = EVS_OK;
+- res_lib_evs_membership_get.local_nodeid = this_ip->nodeid;
++ res_lib_evs_membership_get.local_nodeid = totempg_my_nodeid_get ();
+ memcpy (&res_lib_evs_membership_get.member_list,
+ &res_evs_confchg_callback.member_list,
+ sizeof (res_lib_evs_membership_get.member_list));
+@@ -462,7 +473,9 @@
+ res_lib_evs_membership_get.member_list_entries =
+ res_evs_confchg_callback.member_list_entries;
+
+- openais_conn_send_response (conn, &res_lib_evs_membership_get,
++ openais_response_send (
++ conn,
++ &res_lib_evs_membership_get,
+ sizeof (struct res_lib_evs_membership_get));
+ }
+
+@@ -487,8 +500,10 @@
+ int i, j;
+ struct evs_pd *evs_pd;
+
+- res_evs_deliver_callback.header.size = sizeof (struct res_evs_deliver_callback) +
+- req_exec_evs_mcast->msg_len;
++ res_evs_deliver_callback.header.size =
++ sizeof (struct res_evs_deliver_callback) +
++ req_exec_evs_mcast->msg_len;
++
+ res_evs_deliver_callback.header.id = MESSAGE_RES_EVS_DELIVER_CALLBACK;
+ res_evs_deliver_callback.header.error = SA_AIS_OK;
+ res_evs_deliver_callback.msglen = req_exec_evs_mcast->msg_len;
+@@ -517,9 +532,13 @@
+
+ if (found) {
+ res_evs_deliver_callback.local_nodeid = nodeid;
+- openais_conn_send_response (evs_pd->conn, &res_evs_deliver_callback,
++ openais_dispatch_send (
++ evs_pd->conn,
++ &res_evs_deliver_callback,
+ sizeof (struct res_evs_deliver_callback));
+- openais_conn_send_response (evs_pd->conn, msg_addr,
++ openais_dispatch_send (
++ evs_pd->conn,
++ msg_addr,
+ req_exec_evs_mcast->msg_len);
+ }
+ }
+diff -uNr openais-0.80.3/exec/evt.c openais-0.80.3-r1661/exec/evt.c
+--- openais-0.80.3/exec/evt.c 2007-06-25 04:22:54.000000000 +0200
++++ openais-0.80.3-r1661/exec/evt.c 2008-11-17 15:54:02.390605772 +0100
+@@ -1853,8 +1853,10 @@
+ res.evd_head.size = sizeof(res);
+ res.evd_head.id = MESSAGE_RES_EVT_AVAILABLE;
+ res.evd_head.error = SA_AIS_OK;
+- openais_conn_send_response(openais_conn_partner_get(conn),
+- &res, sizeof(res));
++ openais_dispatch_send (
++ conn,
++ &res,
++ sizeof(res));
+ }
+
+ }
+@@ -1987,6 +1989,7 @@
+ if (!ep) {
+ log_printf(LOG_LEVEL_WARNING,
+ "5Memory allocation error, can't deliver event\n");
++ free (ed);
+ return;
+ }
+ ep->cel_chan_handle = eco->eco_lib_handle;
+@@ -2264,7 +2267,7 @@
+ res.ico_head.size = sizeof(res);
+ res.ico_head.id = MESSAGE_RES_EVT_OPEN_CHANNEL;
+ res.ico_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -2321,7 +2324,7 @@
+ res.ico_head.size = sizeof(res);
+ res.ico_head.id = MESSAGE_RES_EVT_OPEN_CHANNEL;
+ res.ico_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_dispatch_send(conn, &res, sizeof(res));
+ }
+
+
+@@ -2414,7 +2417,7 @@
+ res.icc_head.size = sizeof(res);
+ res.icc_head.id = MESSAGE_RES_EVT_CLOSE_CHANNEL;
+ res.icc_head.error = ((ret == 0) ? SA_AIS_OK : SA_AIS_ERR_BAD_HANDLE);
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -2486,7 +2489,7 @@
+ res.iuc_head.size = sizeof(res);
+ res.iuc_head.id = MESSAGE_RES_EVT_UNLINK_CHANNEL;
+ res.iuc_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -2590,7 +2593,7 @@
+ res.ics_head.size = sizeof(res);
+ res.ics_head.id = MESSAGE_RES_EVT_SUBSCRIBE;
+ res.ics_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+
+ /*
+ * See if an existing event with a retention time
+@@ -2623,7 +2626,7 @@
+ res.ics_head.size = sizeof(res);
+ res.ics_head.id = MESSAGE_RES_EVT_SUBSCRIBE;
+ res.ics_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -2690,7 +2693,7 @@
+ res.icu_head.size = sizeof(res);
+ res.icu_head.id = MESSAGE_RES_EVT_UNSUBSCRIBE;
+ res.icu_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -2762,7 +2765,7 @@
+ res.iep_head.id = MESSAGE_RES_EVT_PUBLISH;
+ res.iep_head.error = error;
+ res.iep_event_id = event_id;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -2826,7 +2829,7 @@
+ res.iec_head.size = sizeof(res);
+ res.iec_head.id = MESSAGE_RES_EVT_CLEAR_RETENTIONTIME;
+ res.iec_head.error = error;
+- openais_conn_send_response(conn, &res, sizeof(res));
++ openais_response_send(conn, &res, sizeof(res));
+
+ }
+
+@@ -2865,7 +2868,7 @@
+ edp->ed_event.led_head.id = MESSAGE_RES_EVT_EVENT_DATA;
+ edp->ed_event.led_head.error = SA_AIS_OK;
+ free(cel);
+- openais_conn_send_response(conn, &edp->ed_event,
++ openais_response_send(conn, &edp->ed_event,
+ edp->ed_event.led_head.size);
+ free_event_data(edp);
+ goto data_get_done;
+@@ -2875,7 +2878,7 @@
+ res.led_head.size = sizeof(res.led_head);
+ res.led_head.id = MESSAGE_RES_EVT_EVENT_DATA;
+ res.led_head.error = SA_AIS_ERR_NOT_EXIST;
+- openais_conn_send_response(conn, &res, res.led_head.size);
++ openais_response_send(conn, &res, res.led_head.size);
+
+ /*
+ * See if there are any events that the app doesn't know about
+@@ -3037,7 +3040,7 @@
+ struct unlink_chan_pending *ucp;
+ struct retention_time_clear_pending *rtc;
+ struct libevt_pd *esip =
+- openais_conn_private_data_get(openais_conn_partner_get(conn));
++ openais_conn_private_data_get(conn);
+
+ log_printf(LOG_LEVEL_DEBUG, "saEvtFinalize (Event exit request)\n");
+ log_printf(LOG_LEVEL_DEBUG, "saEvtFinalize %d evts on list\n",
+@@ -3430,7 +3433,7 @@
+ res.ico_head.id = MESSAGE_RES_EVT_OPEN_CHANNEL;
+ res.ico_head.error = SA_AIS_ERR_TIMEOUT;
+ ocp->ocp_invocation = OPEN_TIMED_OUT;
+- openais_conn_send_response(ocp->ocp_conn, &res, sizeof(res));
++ openais_response_send(ocp->ocp_conn, &res, sizeof(res));
+ }
+
+ /*
+@@ -3520,15 +3523,14 @@
+ resa.ica_channel_handle = handle;
+ resa.ica_c_handle = ocp->ocp_c_handle;
+ resa.ica_invocation = ocp->ocp_invocation;
+- openais_conn_send_response(openais_conn_partner_get(ocp->ocp_conn),
+- &resa, sizeof(resa));
++ openais_dispatch_send(ocp->ocp_conn, &resa, sizeof(resa));
+ } else {
+ struct res_evt_channel_open res;
+ res.ico_head.size = sizeof(res);
+ res.ico_head.id = MESSAGE_RES_EVT_OPEN_CHANNEL;
+ res.ico_head.error = (ret == 0 ? SA_AIS_OK : SA_AIS_ERR_BAD_HANDLE);
+ res.ico_channel_handle = handle;
+- openais_conn_send_response(ocp->ocp_conn, &res, sizeof(res));
++ openais_response_send(ocp->ocp_conn, &res, sizeof(res));
+ }
+
+ if (timer_del_status == 0) {
+@@ -3553,7 +3555,7 @@
+ res.iuc_head.size = sizeof(res);
+ res.iuc_head.id = MESSAGE_RES_EVT_UNLINK_CHANNEL;
+ res.iuc_head.error = SA_AIS_OK;
+- openais_conn_send_response(ucp->ucp_conn, &res, sizeof(res));
++ openais_response_send(ucp->ucp_conn, &res, sizeof(res));
+
+ free(ucp);
+ }
+@@ -3573,7 +3575,7 @@
+ res.iec_head.size = sizeof(res);
+ res.iec_head.id = MESSAGE_RES_EVT_CLEAR_RETENTIONTIME;
+ res.iec_head.error = ret;
+- openais_conn_send_response(rtc->rtc_conn, &res, sizeof(res));
++ openais_response_send(rtc->rtc_conn, &res, sizeof(res));
+
+ list_del(&rtc->rtc_entry);
+ free(rtc);
+diff -uNr openais-0.80.3/exec/ipc.c openais-0.80.3-r1661/exec/ipc.c
+--- openais-0.80.3/exec/ipc.c 2007-06-25 04:22:54.000000000 +0200
++++ openais-0.80.3-r1661/exec/ipc.c 2008-11-17 15:54:02.380604445 +0100
+@@ -1,5 +1,4 @@
+ /*
+- * Copyright (c) 2002-2006 MontaVista Software, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
+ *
+ * All rights reserved.
+@@ -32,6 +31,9 @@
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
+ #include <pthread.h>
+ #include <assert.h>
+ #include <pwd.h>
+@@ -54,7 +56,11 @@
+ #include <signal.h>
+ #include <sched.h>
+ #include <time.h>
++#if defined(HAVE_GETPEERUCRED)
++#include <ucred.h>
++#endif
+
++#include "swab.h"
+ #include "../include/saAis.h"
+ #include "../include/list.h"
+ #include "../include/queue.h"
+@@ -66,6 +72,8 @@
+ #include "mainconfig.h"
+ #include "totemconfig.h"
+ #include "main.h"
++#include "flow.h"
++#include "tlist.h"
+ #include "ipc.h"
+ #include "flow.h"
+ #include "service.h"
+@@ -79,6 +87,10 @@
+
+ #include "util.h"
+
++#ifdef OPENAIS_SOLARIS
++#define MSG_NOSIGNAL 0
++#endif
++
+ #define SERVER_BACKLOG 5
+
+ /*
+@@ -94,11 +106,11 @@
+
+ static unsigned int g_gid_valid = 0;
+
+-static struct totem_ip_address *my_ip;
+-
+ static totempg_groups_handle ipc_handle;
+
+-DECLARE_LIST_INIT (conn_info_list_head);
++static pthread_mutex_t conn_io_list_mutex = PTHREAD_MUTEX_INITIALIZER;
++
++DECLARE_LIST_INIT (conn_io_list_head);
+
+ static void (*ipc_serialize_lock_fn) (void);
+
+@@ -109,148 +121,282 @@
+ size_t mlen;
+ };
+
+-enum conn_state {
+- CONN_STATE_ACTIVE,
+- CONN_STATE_SECURITY,
+- CONN_STATE_REQUESTED,
+- CONN_STATE_CLOSED,
+- CONN_STATE_DISCONNECTED
++enum conn_io_state {
++ CONN_IO_STATE_INITIALIZING,
++ CONN_IO_STATE_AUTHENTICATED,
++ CONN_IO_STATE_INIT_FAILED
+ };
+
+-struct conn_info {
+- int fd; /* File descriptor */
+- unsigned int events; /* events polled for by file descriptor */
+- enum conn_state state; /* State of this connection */
+- pthread_t thread; /* thread identifier */
++enum conn_info_state {
++ CONN_INFO_STATE_INITIALIZING,
++ CONN_INFO_STATE_ACTIVE,
++ CONN_INFO_STATE_DISCONNECT_REQUESTED,
++ CONN_INFO_STATE_DISCONNECTED
++};
++
++struct conn_info;
++
++struct conn_io {
++ int fd; /* File descriptor */
++ unsigned int events; /* events polled for by file descriptor */
++ pthread_t thread; /* thread identifier */
+ pthread_attr_t thread_attr; /* thread attribute */
+- char *inb; /* Input buffer for non-blocking reads */
+- int inb_nextheader; /* Next message header starts here */
+- int inb_start; /* Start location of input buffer */
+- int inb_inuse; /* Bytes currently stored in input buffer */
+- struct queue outq; /* Circular queue for outgoing requests */
+- int byte_start; /* Byte to start sending from in head of queue */
+- enum service_types service;/* Type of service so dispatch knows how to route message */
+- int authenticated; /* Is this connection authenticated? */
+- void *private_data; /* library connection private data */
+- struct conn_info *conn_info_partner; /* partner connection dispatch<->response */
++ char *inb; /* Input buffer for non-blocking reads */
++ int inb_nextheader; /* Next message header starts here */
++ int inb_start; /* Start location of input buffer */
++ int inb_inuse; /* Bytes currently stored in input buffer */
++ struct queue outq; /* Circular queue for outgoing requests */
++ int byte_start; /* Byte to start sending from in head of queue */
++ unsigned int fcc; /* flow control local count */
++ enum conn_io_state state; /* state of this conn_io connection */
++ struct conn_info *conn_info; /* connection information combining multiple conn_io structs */
++ unsigned int refcnt; /* reference count for conn_io data structure */
++ pthread_mutex_t mutex;
++ unsigned int service;
++ struct list_head list;
++};
++
++
++struct conn_info {
++ enum conn_info_state state; /* State of this connection */
++ enum service_types service; /* Type of service so dispatch knows how to route message */
++ void *private_data; /* library connection private data */
+ unsigned int flow_control_handle; /* flow control identifier */
+ unsigned int flow_control_enabled; /* flow control enabled bit */
+- unsigned int flow_control_local_count; /* flow control local count */
+ enum openais_flow_control flow_control; /* Does this service use IPC flow control */
+ pthread_mutex_t flow_control_mutex;
++ unsigned int flow_control_local_count; /* flow control local count */
+ int (*lib_exit_fn) (void *conn);
+- struct timerlist timerlist;
+ pthread_mutex_t mutex;
+- pthread_mutex_t *shared_mutex;
+- struct list_head list;
++ struct conn_io *conn_io_response;
++ struct conn_io *conn_io_dispatch;
++ unsigned int refcnt;
+ };
+
+-static void *prioritized_poll_thread (void *conn);
+-static int conn_info_outq_flush (struct conn_info *conn_info);
+-static void libais_deliver (struct conn_info *conn_info);
+-static void ipc_flow_control (struct conn_info *conn_info);
++static void *prioritized_poll_thread (void *conn_io_in);
++static int conn_io_outq_flush (struct conn_io *conn_io);
++static void conn_io_deliver (struct conn_io *conn_io);
++//static void ipc_flow_control (struct conn_info *conn_info);
++static inline void conn_info_destroy (struct conn_info *conn_info);
++static void conn_io_destroy (struct conn_io *conn_io);
++static int conn_io_send (struct conn_io *conn_io, void *msg, int mlen);
++static inline struct conn_info *conn_info_create (void);
++static int conn_io_found (struct conn_io *conn_io_to_match);
++
++static int response_init_send (struct conn_io *conn_io, void *message);
++static int dispatch_init_send (struct conn_io *conn_io, void *message);
+
+ /*
+ * IPC Initializers
+ */
+
+-static int response_init_send_response (
+- struct conn_info *conn_info,
+- void *message);
+-static int dispatch_init_send_response (
+- struct conn_info *conn_info,
+- void *message);
+-
+-static int (*ais_init_service[]) (struct conn_info *conn_info, void *message) = {
+- response_init_send_response,
+- dispatch_init_send_response
++static int conn_io_refcnt_value (struct conn_io *conn_io)
++{
++ unsigned int refcnt;
++
++ pthread_mutex_lock (&conn_io->mutex);
++ refcnt = conn_io->refcnt;
++ pthread_mutex_unlock (&conn_io->mutex);
++
++ return (refcnt);
++}
++
++static void conn_io_refcnt_inc (struct conn_io *conn_io)
++{
++ pthread_mutex_lock (&conn_io->mutex);
++ conn_io->refcnt += 1;
++ pthread_mutex_unlock (&conn_io->mutex);
++}
++
++static int conn_io_refcnt_dec (struct conn_io *conn_io)
++{
++ unsigned int refcnt;
++
++ pthread_mutex_lock (&conn_io->mutex);
++ conn_io->refcnt -= 1;
++ refcnt = conn_io->refcnt;
++ pthread_mutex_unlock (&conn_io->mutex);
++
++ return (refcnt);
++}
++
++static void conn_info_refcnt_inc (struct conn_info *conn_info)
++{
++ /*
++ * Connection not fully initialized yet
++ */
++ if (conn_info == NULL) {
++ return;
++ }
++ pthread_mutex_lock (&conn_info->mutex);
++ conn_info->refcnt += 1;
++ pthread_mutex_unlock (&conn_info->mutex);
++}
++
++static void conn_info_refcnt_dec (struct conn_info *conn_info)
++{
++ int refcnt;
++
++ /*
++ * Connection not fully initialized yet
++ */
++ if (conn_info == NULL) {
++ return;
++ }
++ pthread_mutex_lock (&conn_info->mutex);
++ conn_info->refcnt -= 1;
++ refcnt = conn_info->refcnt;
++ assert (refcnt >= 0);
++ pthread_mutex_unlock (&conn_info->mutex);
++
++ if (refcnt == 0) {
++ conn_info_destroy (conn_info);
++ }
++}
++
++void openais_conn_info_refcnt_dec (void *conn)
++{
++ struct conn_info *conn_info = (struct conn_info *)conn;
++
++ conn_info_refcnt_dec (conn_info);
++}
++
++void openais_conn_info_refcnt_inc (void *conn)
++{
++ struct conn_info *conn_info = (struct conn_info *)conn;
++
++ conn_info_refcnt_inc (conn_info);
++}
++
++static int (*ais_init_service[]) (struct conn_io *conn_io, void *message) = {
++ response_init_send,
++ dispatch_init_send
+ };
+
+-static void libais_disconnect_security (struct conn_info *conn_info)
++static void disconnect_request (struct conn_info *conn_info)
+ {
+- conn_info->state = CONN_STATE_SECURITY;
+- close (conn_info->fd);
++unsigned int res;
++ /*
++ * connection not fully active yet
++ */
++ if (conn_info == NULL) {
++ return;
++ }
++ /*
++ * We only want to decrement the reference count on these two
++ * conn_io contexts one time
++ */
++ if (conn_info->state != CONN_INFO_STATE_ACTIVE) {
++ return;
++ }
++ res = conn_io_refcnt_dec (conn_info->conn_io_response);
++ res = conn_io_refcnt_dec (conn_info->conn_io_dispatch);
++ conn_info->state = CONN_INFO_STATE_DISCONNECT_REQUESTED;
+ }
+
+-static int response_init_send_response (
+- struct conn_info *conn_info,
++static int response_init_send (
++ struct conn_io *conn_io,
+ void *message)
+ {
+ SaAisErrorT error = SA_AIS_ERR_ACCESS;
+- uintptr_t cinfo = (uintptr_t)conn_info;
++ uintptr_t cinfo = (uintptr_t)conn_io;
+ mar_req_lib_response_init_t *req_lib_response_init = (mar_req_lib_response_init_t *)message;
+ mar_res_lib_response_init_t res_lib_response_init;
+
+- if (conn_info->authenticated) {
+- conn_info->service = req_lib_response_init->resdis_header.service;
++ if (conn_io->state == CONN_IO_STATE_AUTHENTICATED) {
+ error = SA_AIS_OK;
++ conn_io->service = req_lib_response_init->resdis_header.service;
+ }
+ res_lib_response_init.header.size = sizeof (mar_res_lib_response_init_t);
+ res_lib_response_init.header.id = MESSAGE_RES_INIT;
+ res_lib_response_init.header.error = error;
+ res_lib_response_init.conn_info = (mar_uint64_t)cinfo;
+
+- openais_conn_send_response (
+- conn_info,
++ conn_io_send (
++ conn_io,
+ &res_lib_response_init,
+ sizeof (res_lib_response_init));
+
+ if (error == SA_AIS_ERR_ACCESS) {
+- libais_disconnect_security (conn_info);
++ conn_io_destroy (conn_io);
+ return (-1);
+ }
++
+ return (0);
+ }
+
+-static int dispatch_init_send_response (
+- struct conn_info *conn_info,
++/*
++ * This is called iwth ipc_serialize_lock_fn() called
++ * Therefore there are no races with the destruction of the conn_io
++ * data structure
++ */
++static int dispatch_init_send (
++ struct conn_io *conn_io,
+ void *message)
+ {
+ SaAisErrorT error = SA_AIS_ERR_ACCESS;
+ uintptr_t cinfo;
+ mar_req_lib_dispatch_init_t *req_lib_dispatch_init = (mar_req_lib_dispatch_init_t *)message;
+ mar_res_lib_dispatch_init_t res_lib_dispatch_init;
+- struct conn_info *msg_conn_info;
++ struct conn_io *msg_conn_io;
++ struct conn_info *conn_info;
++ unsigned int service;
++
++ service = req_lib_dispatch_init->resdis_header.service;
++ cinfo = (uintptr_t)req_lib_dispatch_init->conn_info;
++ msg_conn_io = (struct conn_io *)cinfo;
+
+- if (conn_info->authenticated) {
+- conn_info->service = req_lib_dispatch_init->resdis_header.service;
+- if (!ais_service[req_lib_dispatch_init->resdis_header.service])
++ /*
++ * The response IPC connection has disconnected already for
++ * some reason and is no longer referenceable in the system
++ */
++ if (conn_io->state == CONN_IO_STATE_AUTHENTICATED) {
++ /*
++ * If the response conn_io isn't found, it disconnected.
++ * Hence, a full connection cannot be made and this connection
++ * should be aborted by the poll thread
++ */
++ if (conn_io_found (msg_conn_io) == 0) {
++ error = SA_AIS_ERR_TRY_AGAIN;
++ conn_io->state = CONN_IO_STATE_INIT_FAILED;
++ } else
++ /*
++ * If no service is found for the requested library service,
++ * the proper service handler isn't loaded and this connection
++ * should be aborted by the poll thread
++ */
++ if (ais_service[service] == NULL) {
+ error = SA_AIS_ERR_NOT_SUPPORTED;
+- else
++ conn_io->state = CONN_IO_STATE_INIT_FAILED;
++ } else {
+ error = SA_AIS_OK;
++ }
+
+- cinfo = (uintptr_t)req_lib_dispatch_init->conn_info;
+- conn_info->conn_info_partner = (struct conn_info *)cinfo;
+-
+- /* temporary fix for memory leak
++ /*
++ * The response and dispatch conn_io structures are available.
++ * Attempt to allocate the appropriate memory for the private
++ * data area
+ */
+- pthread_mutex_destroy (conn_info->conn_info_partner->shared_mutex);
+- free (conn_info->conn_info_partner->shared_mutex);
+-
+- conn_info->conn_info_partner->shared_mutex = conn_info->shared_mutex;
+-
+- list_add (&conn_info_list_head, &conn_info->list);
+- list_add (&conn_info_list_head, &conn_info->conn_info_partner->list);
+-
+- msg_conn_info = (struct conn_info *)cinfo;
+- msg_conn_info->conn_info_partner = conn_info;
+-
+ if (error == SA_AIS_OK) {
+ int private_data_size;
+
+- private_data_size = ais_service[req_lib_dispatch_init->resdis_header.service]->private_data_size;
++ conn_info = conn_info_create ();
++ private_data_size = ais_service[service]->private_data_size;
+ if (private_data_size) {
+ conn_info->private_data = malloc (private_data_size);
+
+- conn_info->conn_info_partner->private_data = conn_info->private_data;
++ /*
++ * No private data could be allocated so
++ * request the poll thread to abort
++ */
+ if (conn_info->private_data == NULL) {
++ conn_io->state = CONN_IO_STATE_INIT_FAILED;
+ error = SA_AIS_ERR_NO_MEMORY;
+ } else {
+ memset (conn_info->private_data, 0, private_data_size);
+ }
+ } else {
+ conn_info->private_data = NULL;
+- conn_info->conn_info_partner->private_data = NULL;
+ }
+ }
+ }
+@@ -259,287 +405,203 @@
+ res_lib_dispatch_init.header.id = MESSAGE_RES_INIT;
+ res_lib_dispatch_init.header.error = error;
+
+- openais_conn_send_response (
+- conn_info,
+- &res_lib_dispatch_init,
+- sizeof (res_lib_dispatch_init));
+-
+- if (error == SA_AIS_ERR_ACCESS) {
+- libais_disconnect_security (conn_info);
+- return (-1);
+- }
+ if (error != SA_AIS_OK) {
++ conn_io_send (
++ conn_io,
++ &res_lib_dispatch_init,
++ sizeof (res_lib_dispatch_init));
++
+ return (-1);
+ }
+
+- conn_info->state = CONN_STATE_ACTIVE;
+- conn_info->conn_info_partner->state = CONN_STATE_ACTIVE;
+- conn_info->lib_exit_fn = ais_service[conn_info->service]->lib_exit_fn;
++ /*
++ * connect both dispatch and response conn_ios into the conn_info
++ * data structure
++ */
++ conn_info->state = CONN_INFO_STATE_ACTIVE;
++ conn_info->lib_exit_fn = ais_service[service]->lib_exit_fn;
++ conn_info->conn_io_response = msg_conn_io;
++ conn_info->conn_io_response->conn_info = conn_info;
++ conn_info->conn_io_dispatch = conn_io;
++ conn_info->service = service;
++ conn_io->service = service;
++ conn_io->conn_info = conn_info;
+ ais_service[conn_info->service]->lib_init_fn (conn_info);
+
+ conn_info->flow_control = ais_service[conn_info->service]->flow_control;
+- conn_info->conn_info_partner->flow_control = ais_service[conn_info->service]->flow_control;
+ if (ais_service[conn_info->service]->flow_control == OPENAIS_FLOW_CONTROL_REQUIRED) {
+ openais_flow_control_ipc_init (
+ &conn_info->flow_control_handle,
+ conn_info->service);
+
+ }
++
++ /*
++ * Tell the library the IPC connections are configured
++ */
++ conn_io_send (
++ conn_io,
++ &res_lib_dispatch_init,
++ sizeof (res_lib_dispatch_init));
+ return (0);
+ }
+
+ /*
+ * Create a connection data structure
+ */
+-static inline unsigned int conn_info_create (int fd) {
++static inline struct conn_info *conn_info_create (void)
++{
+ struct conn_info *conn_info;
+- int res;
+
+ conn_info = malloc (sizeof (struct conn_info));
+ if (conn_info == 0) {
+- return (ENOMEM);
++ return (NULL);
+ }
+
+ memset (conn_info, 0, sizeof (struct conn_info));
+
+- res = queue_init (&conn_info->outq, SIZEQUEUE,
++ conn_info->refcnt = 2;
++ pthread_mutex_init (&conn_info->mutex, NULL);
++ conn_info->state = CONN_INFO_STATE_INITIALIZING;
++
++ return (conn_info);
++}
++
++static inline void conn_info_destroy (struct conn_info *conn_info)
++{
++ if (conn_info->private_data) {
++ free (conn_info->private_data);
++ }
++ pthread_mutex_destroy (&conn_info->mutex);
++ free (conn_info);
++}
++
++static int conn_io_create (int fd)
++{
++ int res;
++ struct conn_io *conn_io;
++
++ conn_io = malloc (sizeof (struct conn_io));
++ if (conn_io == NULL) {
++ return (-1);
++ }
++ memset (conn_io, 0, sizeof (struct conn_io));
++
++ res = queue_init (&conn_io->outq, SIZEQUEUE,
+ sizeof (struct outq_item));
+ if (res != 0) {
+- free (conn_info);
+- return (ENOMEM);
++ return (-1);
+ }
+- conn_info->inb = malloc (sizeof (char) * SIZEINB);
+- if (conn_info->inb == NULL) {
+- queue_free (&conn_info->outq);
+- free (conn_info);
+- return (ENOMEM);
+- }
+- conn_info->shared_mutex = malloc (sizeof (pthread_mutex_t));
+- if (conn_info->shared_mutex == NULL) {
+- free (conn_info->inb);
+- queue_free (&conn_info->outq);
+- free (conn_info);
+- return (ENOMEM);
++
++ conn_io->inb = malloc (sizeof (char) * SIZEINB);
++ if (conn_io->inb == NULL) {
++ queue_free (&conn_io->outq);
++ return (-1);
+ }
+
+- pthread_mutex_init (&conn_info->mutex, NULL);
+- pthread_mutex_init (&conn_info->flow_control_mutex, NULL);
+- pthread_mutex_init (conn_info->shared_mutex, NULL);
++ conn_io->fd = fd;
++ conn_io->events = POLLIN|POLLNVAL;
++ conn_io->refcnt = 1;
++ conn_io->service = SOCKET_SERVICE_INIT;
++ conn_io->state = CONN_IO_STATE_INITIALIZING;
+
+- list_init (&conn_info->list);
+- conn_info->state = CONN_STATE_ACTIVE;
+- conn_info->fd = fd;
+- conn_info->events = POLLIN|POLLNVAL;
+- conn_info->service = SOCKET_SERVICE_INIT;
++ pthread_attr_init (&conn_io->thread_attr);
+
+- pthread_attr_init (&conn_info->thread_attr);
+-/*
+- * IA64 needs more stack space then other arches
+- */
++ pthread_mutex_init (&conn_io->mutex, NULL);
++
++ /*
++ * IA64 needs more stack space then other arches
++ */
+ #if defined(__ia64__)
+- pthread_attr_setstacksize (&conn_info->thread_attr, 400000);
++ pthread_attr_setstacksize (&conn_io->thread_attr, 400000);
+ #else
+- pthread_attr_setstacksize (&conn_info->thread_attr, 200000);
++ pthread_attr_setstacksize (&conn_io->thread_attr, 200000);
+ #endif
+
+- pthread_attr_setdetachstate (&conn_info->thread_attr, PTHREAD_CREATE_DETACHED);
+- res = pthread_create (&conn_info->thread, &conn_info->thread_attr,
+- prioritized_poll_thread, conn_info);
++ pthread_attr_setdetachstate (&conn_io->thread_attr, PTHREAD_CREATE_DETACHED);
++
++ res = pthread_create (&conn_io->thread, &conn_io->thread_attr,
++ prioritized_poll_thread, conn_io);
++
++ list_init (&conn_io->list);
++
++ pthread_mutex_lock (&conn_io_list_mutex);
++ list_add (&conn_io->list, &conn_io_list_head);
++ pthread_mutex_unlock (&conn_io_list_mutex);
+ return (res);
+ }
+
+-static void conn_info_destroy (struct conn_info *conn_info)
++static void conn_io_destroy (struct conn_io *conn_io)
+ {
+ struct outq_item *outq_item;
+
+ /*
+ * Free the outq queued items
+ */
+- while (!queue_is_empty (&conn_info->outq)) {
+- outq_item = queue_item_get (&conn_info->outq);
++ while (!queue_is_empty (&conn_io->outq)) {
++ outq_item = queue_item_get (&conn_io->outq);
+ free (outq_item->msg);
+- queue_item_remove (&conn_info->outq);
++ queue_item_remove (&conn_io->outq);
+ }
+
+- queue_free (&conn_info->outq);
+- free (conn_info->inb);
+- if (conn_info->conn_info_partner) {
+- conn_info->conn_info_partner->conn_info_partner = NULL;
+- }
++ queue_free (&conn_io->outq);
++ free (conn_io->inb);
++ close (conn_io->fd);
++ pthread_mutex_lock (&conn_io_list_mutex);
++ list_del (&conn_io->list);
++ pthread_mutex_unlock (&conn_io_list_mutex);
+
+- pthread_attr_destroy (&conn_info->thread_attr);
+- pthread_mutex_destroy (&conn_info->mutex);
+-
+- list_del (&conn_info->list);
+- free (conn_info);
+-}
+-
+-static int libais_connection_active (struct conn_info *conn_info)
+-{
+- return (conn_info->state == CONN_STATE_ACTIVE);
++ pthread_attr_destroy (&conn_io->thread_attr);
++ pthread_mutex_destroy (&conn_io->mutex);
++ free (conn_io);
+ }
+
+-static void libais_disconnect_request (struct conn_info *conn_info)
++static int conn_io_found (struct conn_io *conn_io_to_match)
+ {
+- if (conn_info->state == CONN_STATE_ACTIVE) {
+- conn_info->state = CONN_STATE_REQUESTED;
+- conn_info->conn_info_partner->state = CONN_STATE_REQUESTED;
+- }
+-}
++ struct list_head *list;
++ struct conn_io *conn_io;
+
+-static int libais_disconnect (struct conn_info *conn_info)
+-{
+- int res = 0;
+-
+- assert (conn_info->state != CONN_STATE_ACTIVE);
+-
+- if (conn_info->state == CONN_STATE_DISCONNECTED) {
+- assert (0);
+- }
+-
+- /*
+- * Close active connections
+- */
+- if (conn_info->state == CONN_STATE_ACTIVE || conn_info->state == CONN_STATE_REQUESTED) {
+- close (conn_info->fd);
+- conn_info->state = CONN_STATE_CLOSED;
+- close (conn_info->conn_info_partner->fd);
+- conn_info->conn_info_partner->state = CONN_STATE_CLOSED;
+- }
+-
+- /*
+- * Note we will only call the close operation once on the first time
+- * one of the connections is closed
+- */
+- if (conn_info->state == CONN_STATE_CLOSED) {
+- if (conn_info->lib_exit_fn) {
+- res = conn_info->lib_exit_fn (conn_info);
+- }
+- if (res == -1) {
+- return (-1);
+- }
+- if (conn_info->conn_info_partner->lib_exit_fn) {
+- res = conn_info->conn_info_partner->lib_exit_fn (conn_info);
+- }
+- if (res == -1) {
+- return (-1);
++ for (list = conn_io_list_head.next; list != &conn_io_list_head;
++ list = list->next) {
++
++ conn_io = list_entry (list, struct conn_io, list);
++ if (conn_io == conn_io_to_match) {
++ return (1);
+ }
+ }
+- conn_info->state = CONN_STATE_DISCONNECTED;
+- conn_info->conn_info_partner->state = CONN_STATE_DISCONNECTED;
+- if (conn_info->flow_control_enabled == 1) {
+- openais_flow_control_disable (conn_info->flow_control_handle);
+- }
+- return (0);
+-}
+
+-static inline void conn_info_mutex_lock (
+- struct conn_info *conn_info,
+- unsigned int service)
+-{
+- if (service == SOCKET_SERVICE_INIT) {
+- pthread_mutex_lock (&conn_info->mutex);
+- } else {
+- pthread_mutex_lock (conn_info->shared_mutex);
+- }
+-}
+-static inline void conn_info_mutex_unlock (
+- struct conn_info *conn_info,
+- unsigned int service)
+-{
+- if (service == SOCKET_SERVICE_INIT) {
+- pthread_mutex_unlock (&conn_info->mutex);
+- } else {
+- pthread_mutex_unlock (conn_info->shared_mutex);
+- }
++ return (0);
+ }
+
+ /*
+ * This thread runs in a specific thread priority mode to handle
+- * I/O requests from the library
++ * I/O requests from or to the library
+ */
+-static void *prioritized_poll_thread (void *conn)
++static void *prioritized_poll_thread (void *conn_io_in)
+ {
+- struct conn_info *conn_info = (struct conn_info *)conn;
++ struct conn_io *conn_io = (struct conn_io *)conn_io_in;
++ struct conn_info *conn_info = NULL;
+ struct pollfd ufd;
+ int fds;
+ struct sched_param sched_param;
+ int res;
+- pthread_mutex_t *rel_mutex;
+- unsigned int service;
+- struct conn_info *cinfo_partner;
+- void *private_data;
+
+-#if defined(OPENAIS_BSD) || defined(OPENAIS_LINUX)
+- res = sched_get_priority_max (SCHED_RR);
+- if (res != -1) {
+- sched_param.sched_priority = res;
+- res = pthread_setschedparam (conn_info->thread, SCHED_RR, &sched_param);
+- if (res == -1) {
+- log_printf (LOG_LEVEL_WARNING, "Could not set SCHED_RR at priority %d: %s\n",
+- sched_param.sched_priority, strerror (errno));
+- }
+- } else
+- log_printf (LOG_LEVEL_WARNING, "Could not get maximum scheduler priority: %s\n", strerror (errno));
+-#else
+- log_printf(LOG_LEVEL_WARNING, "Scheduler priority left to default value (no OS support)\n");
+-#endif
++ sched_param.sched_priority = 99;
++ res = pthread_setschedparam (conn_io->thread, SCHED_RR, &sched_param);
+
+- ufd.fd = conn_info->fd;
++ ufd.fd = conn_io->fd;
+ for (;;) {
+ retry_poll:
+- service = conn_info->service;
+- ufd.events = conn_info->events;
++ conn_info = conn_io->conn_info;
++ conn_io_refcnt_inc (conn_io);
++ conn_info_refcnt_inc (conn_info);
++
++ ufd.events = conn_io->events;
+ ufd.revents = 0;
+ fds = poll (&ufd, 1, -1);
+-
+- conn_info_mutex_lock (conn_info, service);
+-
+- switch (conn_info->state) {
+- case CONN_STATE_SECURITY:
+- conn_info_mutex_unlock (conn_info, service);
+- pthread_mutex_destroy (conn_info->shared_mutex);
+- free (conn_info->shared_mutex);
+- conn_info_destroy (conn);
+- pthread_exit (0);
+- break;
+-
+- case CONN_STATE_REQUESTED:
+- case CONN_STATE_CLOSED:
+- res = libais_disconnect (conn);
+- if (res != 0) {
+- conn_info_mutex_unlock (conn_info, service);
+- goto retry_poll;
+- }
+- break;
+-
+- case CONN_STATE_DISCONNECTED:
+- rel_mutex = conn_info->shared_mutex;
+- private_data = conn_info->private_data;
+- cinfo_partner = conn_info->conn_info_partner;
+- conn_info_destroy (conn);
+- if (service == SOCKET_SERVICE_INIT) {
+- pthread_mutex_unlock (&conn_info->mutex);
+- } else {
+- pthread_mutex_unlock (rel_mutex);
+- }
+- if (cinfo_partner == NULL) {
+- pthread_mutex_destroy (rel_mutex);
+- free (rel_mutex);
+- free (private_data);
+- }
+- pthread_exit (0);
+- /*
+- * !! NOTE !! this is the exit point for this thread
+- */
+- break;
+-
+- default:
+- break;
+- }
+-
+ if (fds == -1) {
+- conn_info_mutex_unlock (conn_info, service);
++ conn_io_refcnt_dec (conn_io);
++ conn_info_refcnt_dec (conn_info);
+ goto retry_poll;
+ }
+
+@@ -547,49 +609,151 @@
+
+ if (fds == 1 && ufd.revents) {
+ if (ufd.revents & (POLLERR|POLLHUP)) {
++ disconnect_request (conn_info);
++ conn_info_refcnt_dec (conn_info);
++ conn_io_refcnt_dec (conn_io);
++ /*
++ * If conn_info not set, wait for it to be set
++ * else break out of for loop
++ */
++ if (conn_info == NULL) {
++ ipc_serialize_unlock_fn ();
++ continue;
++ } else {
++ ipc_serialize_unlock_fn ();
++ break;
++ }
++ }
+
+- libais_disconnect_request (conn_info);
+-
+- conn_info_mutex_unlock (conn_info, service);
++ if (conn_info && conn_info->state == CONN_INFO_STATE_DISCONNECT_REQUESTED) {
++ conn_info_refcnt_dec (conn_info);
++ conn_io_refcnt_dec (conn_io);
+ ipc_serialize_unlock_fn ();
+- continue;
++ break;
+ }
+
+ if (ufd.revents & POLLOUT) {
+- conn_info_outq_flush (conn_info);
++ conn_io_outq_flush (conn_io);
+ }
+
+ if ((ufd.revents & POLLIN) == POLLIN) {
+- libais_deliver (conn_info);
++ conn_io_deliver (conn_io);
+ }
+
+- ipc_flow_control (conn_info);
++ /*
++ * IPC initializiation failed because response fd
++ * disconnected before it was linked to dispatch fd
++ */
++ if (conn_io->state == CONN_IO_STATE_INIT_FAILED) {
++ conn_io_destroy (conn_io);
++ conn_info_refcnt_dec (conn_info);
++ ipc_serialize_unlock_fn ();
++ pthread_exit (0);
++ }
++ /*
++ * IPC initializiation failed because response fd
++ * disconnected before it was linked to dispatch fd
++ */
++ if (conn_io->state == CONN_IO_STATE_INIT_FAILED) {
++ break;
++ }
++
++// ipc_flow_control (conn_info);
+
+ }
+
+ ipc_serialize_unlock_fn ();
+- conn_info_mutex_unlock (conn_info, service);
++
++ conn_io_refcnt_dec (conn_io);
++ conn_info_refcnt_dec (conn_info);
++ }
++
++ ipc_serialize_lock_fn ();
++
++ /*
++ * IPC initializiation failed because response fd
++ * disconnected before it was linked to dispatch fd
++ */
++ if (conn_io->conn_info == NULL || conn_io->state == CONN_IO_STATE_INIT_FAILED) {
++ conn_io_destroy (conn_io);
++ conn_info_refcnt_dec (conn_info);
++ ipc_serialize_unlock_fn ();
++ pthread_exit (0);
+ }
+
++ conn_info = conn_io->conn_info;
++
++ /*
++ * This is the response conn_io
++ */
++ if (conn_info->conn_io_response == conn_io) {
++ for (;;) {
++ if (conn_io_refcnt_value (conn_io) == 0) {
++ conn_io->conn_info = NULL;
++ conn_io_destroy (conn_io);
++ conn_info_refcnt_dec (conn_info);
++ ipc_serialize_unlock_fn ();
++ pthread_exit (0);
++ }
++ usleep (1000);
++ printf ("sleep 1\n");
++ }
++ } /* response conn_io */
++
++ /*
++ * This is the dispatch conn_io
++ */
++ if (conn_io->conn_info->conn_io_dispatch == conn_io) {
++ ipc_serialize_unlock_fn ();
++ for (;;) {
++ ipc_serialize_lock_fn ();
++ if (conn_io_refcnt_value (conn_io) == 0) {
++ res = 0; // TODO
++ /*
++ * Execute the library exit function
++ */
++ if (conn_io->conn_info->lib_exit_fn) {
++ res = conn_io->conn_info->lib_exit_fn (conn_info);
++ }
++ if (res == 0) {
++ if (conn_io->conn_info->flow_control_enabled == 1) {
++// openais_flow_control_disable (
++// conn_info->flow_control_handle);
++ }
++ conn_io->conn_info = NULL;
++ conn_io_destroy (conn_io);
++ conn_info_refcnt_dec (conn_info);
++ ipc_serialize_unlock_fn ();
++ pthread_exit (0);
++ }
++ } /* refcnt == 0 */
++ ipc_serialize_unlock_fn ();
++ usleep (1000);
++ } /* for (;;) */
++ } /* dispatch conn_io */
++
+ /*
+ * This code never reached
+ */
+ return (0);
+ }
+
+-#if defined(OPENAIS_LINUX)
++#if defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS)
+ /* SUN_LEN is broken for abstract namespace
+ */
+ #define AIS_SUN_LEN(a) sizeof(*(a))
+-
+-char *socketname = "libais.socket";
+ #else
+ #define AIS_SUN_LEN(a) SUN_LEN(a)
++#endif
+
++#if defined(OPENAIS_LINUX)
++char *socketname = "libais.socket";
++#else
+ char *socketname = "/var/run/libais.socket";
+ #endif
+
+
++#ifdef COMPILOE_OUT
+ static void ipc_flow_control (struct conn_info *conn_info)
+ {
+ unsigned int entries_used;
+@@ -647,8 +811,9 @@
+ }
+ }
+ }
++#endif
+
+-static int conn_info_outq_flush (struct conn_info *conn_info) {
++static int conn_io_outq_flush (struct conn_io *conn_io) {
+ struct queue *outq;
+ int res = 0;
+ struct outq_item *queue_item;
+@@ -656,46 +821,51 @@
+ struct iovec iov_send;
+ char *msg_addr;
+
+- if (!libais_connection_active (conn_info)) {
+- return (-1);
+- }
+- outq = &conn_info->outq;
++ outq = &conn_io->outq;
+
+ msg_send.msg_iov = &iov_send;
+ msg_send.msg_name = 0;
+ msg_send.msg_namelen = 0;
+ msg_send.msg_iovlen = 1;
++#ifndef OPENAIS_SOLARIS
+ msg_send.msg_control = 0;
+ msg_send.msg_controllen = 0;
+ msg_send.msg_flags = 0;
++#else
++ msg_send.msg_accrights = 0;
++ msg_send.msg_accrightslen = 0;
++#endif
+
++ pthread_mutex_lock (&conn_io->mutex);
+ while (!queue_is_empty (outq)) {
+ queue_item = queue_item_get (outq);
+ msg_addr = (char *)queue_item->msg;
+- msg_addr = &msg_addr[conn_info->byte_start];
++ msg_addr = &msg_addr[conn_io->byte_start];
+
+ iov_send.iov_base = msg_addr;
+- iov_send.iov_len = queue_item->mlen - conn_info->byte_start;
++ iov_send.iov_len = queue_item->mlen - conn_io->byte_start;
+
+ retry_sendmsg:
+- res = sendmsg (conn_info->fd, &msg_send, MSG_NOSIGNAL);
++ res = sendmsg (conn_io->fd, &msg_send, MSG_NOSIGNAL);
+ if (res == -1 && errno == EINTR) {
+ goto retry_sendmsg;
+ }
+ if (res == -1 && errno == EAGAIN) {
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (0);
+ }
+ if (res == -1 && errno == EPIPE) {
+- libais_disconnect_request (conn_info);
++ disconnect_request (conn_io->conn_info);
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (0);
+ }
+ if (res == -1) {
+- printf ("ERRNO is %d\n", errno);
+ assert (0); /* some other unhandled error here */
+ }
+- if (res + conn_info->byte_start != queue_item->mlen) {
+- conn_info->byte_start += res;
++ if (res + conn_io->byte_start != queue_item->mlen) {
++ conn_io->byte_start += res;
+
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (0);
+ }
+
+@@ -703,14 +873,15 @@
+ * Message sent, try sending another message
+ */
+ queue_item_remove (outq);
+- conn_info->byte_start = 0;
++ conn_io->byte_start = 0;
+ free (queue_item->msg);
+ } /* while queue not empty */
+
+ if (queue_is_empty (outq)) {
+- conn_info->events = POLLIN|POLLNVAL;
++ conn_io->events = POLLIN|POLLNVAL;
+ }
+
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (0);
+ }
+
+@@ -721,7 +892,7 @@
+ char buf[4096];
+ };
+
+-static void libais_deliver (struct conn_info *conn_info)
++static void conn_io_deliver (struct conn_io *conn_io)
+ {
+ int res;
+ mar_req_header_t *header;
+@@ -733,9 +904,6 @@
+ char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))];
+ struct ucred *cred;
+ int on = 0;
+-#else
+- uid_t euid;
+- gid_t egid;
+ #endif
+ int send_ok = 0;
+ int send_ok_joined = 0;
+@@ -746,9 +914,10 @@
+ msg_recv.msg_iovlen = 1;
+ msg_recv.msg_name = 0;
+ msg_recv.msg_namelen = 0;
++#ifndef OPENAIS_SOLARIS
+ msg_recv.msg_flags = 0;
+
+- if (conn_info->authenticated) {
++ if (conn_io->state == CONN_IO_STATE_AUTHENTICATED) {
+ msg_recv.msg_control = 0;
+ msg_recv.msg_controllen = 0;
+ } else {
+@@ -756,25 +925,61 @@
+ msg_recv.msg_control = (void *)cmsg_cred;
+ msg_recv.msg_controllen = sizeof (cmsg_cred);
+ #else
+- euid = -1; egid = -1;
+- if (getpeereid(conn_info->fd, &euid, &egid) != -1 &&
+- (euid == 0 || egid == g_gid_valid)) {
+- conn_info->authenticated = 1;
+- }
+- if (conn_info->authenticated == 0) {
+- log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", egid, g_gid_valid);
++ {
++ uid_t euid;
++ gid_t egid;
++
++ euid = -1; egid = -1;
++ if (getpeereid(conn_io->fd, &euid, &egid) != -1 &&
++ (euid == 0 || egid == g_gid_valid)) {
++ conn_io->state = CONN_IO_STATE_AUTHENTICATED;
++ }
++ if (conn_io->state == CONN_IO_STATE_INITIALIZING) {
++ log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", egid, g_gid_valid);
++ }
+ }
+ #endif
+ }
+
+- iov_recv.iov_base = &conn_info->inb[conn_info->inb_start];
+- iov_recv.iov_len = (SIZEINB) - conn_info->inb_start;
+- if (conn_info->inb_inuse == SIZEINB) {
++#else /* OPENAIS_SOLARIS */
++ msg_recv.msg_accrights = 0;
++ msg_recv.msg_accrightslen = 0;
++
++
++ if (! conn_info->authenticated) {
++#ifdef HAVE_GETPEERUCRED
++ ucred_t *uc;
++ uid_t euid = -1;
++ gid_t egid = -1;
++
++ if (getpeerucred (conn_info->fd, &uc) == 0) {
++ euid = ucred_geteuid (uc);
++ egid = ucred_getegid (uc);
++ if ((euid == 0) || (egid == g_gid_valid)) {
++ conn_info->authenticated = 1;
++ }
++ ucred_free(uc);
++ }
++ if (conn_info->authenticated == 0) {
++ log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", (int)egid, g_gid_valid);
++ }
++ #else
++ log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated "
++ "because platform does not support "
++ "authentication with sockets, continuing "
++ "with a fake authentication\n");
++ conn_info->authenticated = 1;
++ #endif
++ }
++ #endif
++ iov_recv.iov_base = &conn_io->inb[conn_io->inb_start];
++ iov_recv.iov_len = (SIZEINB) - conn_io->inb_start;
++ if (conn_io->inb_inuse == SIZEINB) {
+ return;
+ }
+
+ retry_recv:
+- res = recvmsg (conn_info->fd, &msg_recv, MSG_NOSIGNAL);
++ res = recvmsg (conn_io->fd, &msg_recv, MSG_NOSIGNAL);
+ if (res == -1 && errno == EINTR) {
+ goto retry_recv;
+ } else
+@@ -786,7 +991,7 @@
+ /* On many OS poll never return POLLHUP or POLLERR.
+ * EOF is detected when recvmsg return 0.
+ */
+- libais_disconnect_request (conn_info);
++ disconnect_request (conn_io);
+ #endif
+ return;
+ }
+@@ -795,17 +1000,17 @@
+ * Authenticate if this connection has not been authenticated
+ */
+ #ifdef OPENAIS_LINUX
+- if (conn_info->authenticated == 0) {
++ if (conn_io->state == CONN_IO_STATE_INITIALIZING) {
+ cmsg = CMSG_FIRSTHDR (&msg_recv);
+ assert (cmsg);
+ cred = (struct ucred *)CMSG_DATA (cmsg);
+ if (cred) {
+ if (cred->uid == 0 || cred->gid == g_gid_valid) {
+- setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
+- conn_info->authenticated = 1;
++ setsockopt(conn_io->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
++ conn_io->state = CONN_IO_STATE_AUTHENTICATED;
+ }
+ }
+- if (conn_info->authenticated == 0) {
++ if (conn_io->state == CONN_IO_STATE_INITIALIZING) {
+ log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", cred->gid, g_gid_valid);
+ }
+ }
+@@ -814,23 +1019,23 @@
+ * Dispatch all messages received in recvmsg that can be dispatched
+ * sizeof (mar_req_header_t) needed at minimum to do any processing
+ */
+- conn_info->inb_inuse += res;
+- conn_info->inb_start += res;
++ conn_io->inb_inuse += res;
++ conn_io->inb_start += res;
+
+- while (conn_info->inb_inuse >= sizeof (mar_req_header_t) && res != -1) {
+- header = (mar_req_header_t *)&conn_info->inb[conn_info->inb_start - conn_info->inb_inuse];
++ while (conn_io->inb_inuse >= sizeof (mar_req_header_t) && res != -1) {
++ header = (mar_req_header_t *)&conn_io->inb[conn_io->inb_start - conn_io->inb_inuse];
+
+- if (header->size > conn_info->inb_inuse) {
++ if (header->size > conn_io->inb_inuse) {
+ break;
+ }
+- service = conn_info->service;
++ service = conn_io->service;
+
+ /*
+ * If this service is in init phase, initialize service
+ * else handle message using service service
+ */
+- if (service == SOCKET_SERVICE_INIT) {
+- res = ais_init_service[header->id] (conn_info, header);
++ if (conn_io->service == SOCKET_SERVICE_INIT) {
++ res = ais_init_service[header->id] (conn_io, header);
+ } else {
+ /*
+ * Not an init service, but a standard service
+@@ -847,7 +1052,7 @@
+ * to queue a message, otherwise tell the library we are busy and to
+ * try again later
+ */
+- send_ok_joined_iovec.iov_base = header;
++ send_ok_joined_iovec.iov_base = (char *)header;
+ send_ok_joined_iovec.iov_len = header->size;
+ send_ok_joined = totempg_groups_send_ok_joined (openais_group_handle,
+ &send_ok_joined_iovec, 1);
+@@ -860,7 +1065,7 @@
+ (sync_in_process() == 0)));
+
+ if (send_ok) {
+- ais_service[service]->lib_service[header->id].lib_handler_fn(conn_info, header);
++ ais_service[service]->lib_service[header->id].lib_handler_fn(conn_io->conn_info, header);
+ } else {
+
+ /*
+@@ -871,33 +1076,33 @@
+ res_overlay.header.id =
+ ais_service[service]->lib_service[header->id].response_id;
+ res_overlay.header.error = SA_AIS_ERR_TRY_AGAIN;
+- openais_conn_send_response (
+- conn_info,
++ conn_io_send (
++ conn_io,
+ &res_overlay,
+ res_overlay.header.size);
+ }
+ }
+- conn_info->inb_inuse -= header->size;
++ conn_io->inb_inuse -= header->size;
+ } /* while */
+
+- if (conn_info->inb_inuse == 0) {
+- conn_info->inb_start = 0;
++ if (conn_io->inb_inuse == 0) {
++ conn_io->inb_start = 0;
+ } else
+-// BUG if (connections[conn_info->fd].inb_start + connections[conn_info->fd].inb_inuse >= SIZEINB) {
+- if (conn_info->inb_start >= SIZEINB) {
++// BUG if (connections[conn_io->fd].inb_start + connections[conn_io->fd].inb_inuse >= SIZEINB) {
++ if (conn_io->inb_start >= SIZEINB) {
+ /*
+ * If in buffer is full, move it back to start
+ */
+- memmove (conn_info->inb,
+- &conn_info->inb[conn_info->inb_start - conn_info->inb_inuse],
+- sizeof (char) * conn_info->inb_inuse);
+- conn_info->inb_start = conn_info->inb_inuse;
++ memmove (conn_io->inb,
++ &conn_io->inb[conn_io->inb_start - conn_io->inb_inuse],
++ sizeof (char) * conn_io->inb_inuse);
++ conn_io->inb_start = conn_io->inb_inuse;
+ }
+
+ return;
+ }
+
+-static int poll_handler_libais_accept (
++static int poll_handler_accept (
+ poll_handle handle,
+ int fd,
+ int revent,
+@@ -945,7 +1150,7 @@
+
+ log_printf (LOG_LEVEL_DEBUG, "connection received from libais client %d.\n", new_fd);
+
+- res = conn_info_create (new_fd);
++ res = conn_io_create (new_fd);
+ if (res != 0) {
+ close (new_fd);
+ }
+@@ -961,7 +1166,7 @@
+ int ret = 0;
+
+ assert (source != NULL);
+- if (source->nodeid == my_ip->nodeid) {
++ if (source->nodeid == totempg_my_nodeid_get ()) {
+ ret = 1;
+ }
+ return ret;
+@@ -973,7 +1178,7 @@
+ {
+ assert ((source != NULL) && (conn != NULL));
+ memset (source, 0, sizeof (mar_message_source_t));
+- source->nodeid = my_ip->nodeid;
++ source->nodeid = totempg_my_nodeid_get ();
+ source->conn = conn;
+ }
+
+@@ -989,15 +1194,12 @@
+ void openais_ipc_init (
+ void (*serialize_lock_fn) (void),
+ void (*serialize_unlock_fn) (void),
+- unsigned int gid_valid,
+- struct totem_ip_address *my_ip_in)
++ unsigned int gid_valid)
+ {
+ int libais_server_fd;
+ struct sockaddr_un un_addr;
+ int res;
+
+- log_init ("IPC");
+-
+ ipc_serialize_lock_fn = serialize_lock_fn;
+
+ ipc_serialize_unlock_fn = serialize_unlock_fn;
+@@ -1011,7 +1213,7 @@
+ openais_exit_error (AIS_DONE_LIBAIS_SOCKET);
+ };
+
+- totemip_nosigpipe(libais_server_fd);
++ totemip_nosigpipe (libais_server_fd);
+ res = fcntl (libais_server_fd, F_SETFL, O_NONBLOCK);
+ if (res == -1) {
+ log_printf (LOG_LEVEL_ERROR, "Could not set non-blocking operation on server socket: %s\n", strerror (errno));
+@@ -1043,12 +1245,10 @@
+ * Setup libais connection dispatch routine
+ */
+ poll_dispatch_add (aisexec_poll_handle, libais_server_fd,
+- POLLIN, 0, poll_handler_libais_accept);
++ POLLIN, 0, poll_handler_accept);
+
+ g_gid_valid = gid_valid;
+
+- my_ip = my_ip_in;
+-
+ /*
+ * Reset internal state of flow control when
+ * configuration change occurs
+@@ -1067,33 +1267,14 @@
+ {
+ struct conn_info *conn_info = (struct conn_info *)conn;
+
+- if (conn != NULL) {
+- return ((void *)conn_info->private_data);
+- } else {
+- return NULL;
+- }
++ return (conn_info->private_data);
+ }
+
+-/*
+- * Get the conn info partner connection
+- */
+-void *openais_conn_partner_get (void *conn)
+-{
+- struct conn_info *conn_info = (struct conn_info *)conn;
+-
+- if (conn != NULL) {
+- return ((void *)conn_info->conn_info_partner);
+- } else {
+- return NULL;
+- }
+-}
+-
+-int openais_conn_send_response (
+- void *conn,
++static int conn_io_send (
++ struct conn_io *conn_io,
+ void *msg,
+ int mlen)
+ {
+- struct queue *outq;
+ char *cmsg;
+ int res = 0;
+ int queue_empty;
+@@ -1102,47 +1283,47 @@
+ struct msghdr msg_send;
+ struct iovec iov_send;
+ char *msg_addr;
+- struct conn_info *conn_info = (struct conn_info *)conn;
+
+- if (conn_info == NULL) {
+- return -1;
+- }
+-
+- if (!libais_connection_active (conn_info)) {
+- return (-1);
++ if (conn_io == NULL) {
++ assert (0);
+ }
+
+- ipc_flow_control (conn_info);
+-
+- outq = &conn_info->outq;
++// ipc_flow_control (conn_info);
+
+ msg_send.msg_iov = &iov_send;
+ msg_send.msg_name = 0;
+ msg_send.msg_namelen = 0;
+ msg_send.msg_iovlen = 1;
++#ifndef OPENAIS_SOLARIS
+ msg_send.msg_control = 0;
+ msg_send.msg_controllen = 0;
+ msg_send.msg_flags = 0;
++#else
++ msg_send.msg_accrights = 0;
++ msg_send.msg_accrightslen = 0;
++#endif
+
+- if (queue_is_full (outq)) {
++ pthread_mutex_lock (&conn_io->mutex);
++ if (queue_is_full (&conn_io->outq)) {
+ /*
+ * Start a disconnect if we have not already started one
+ * and report that the outgoing queue is full
+ */
+ log_printf (LOG_LEVEL_ERROR, "Library queue is full, disconnecting library connection.\n");
+- libais_disconnect_request (conn_info);
++ disconnect_request (conn_io->conn_info);
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (-1);
+ }
+- while (!queue_is_empty (outq)) {
+- queue_item = queue_item_get (outq);
++ while (!queue_is_empty (&conn_io->outq)) {
++ queue_item = queue_item_get (&conn_io->outq);
+ msg_addr = (char *)queue_item->msg;
+- msg_addr = &msg_addr[conn_info->byte_start];
++ msg_addr = &msg_addr[conn_io->byte_start];
+
+ iov_send.iov_base = msg_addr;
+- iov_send.iov_len = queue_item->mlen - conn_info->byte_start;
++ iov_send.iov_len = queue_item->mlen - conn_io->byte_start;
+
+ retry_sendmsg:
+- res = sendmsg (conn_info->fd, &msg_send, MSG_NOSIGNAL);
++ res = sendmsg (conn_io->fd, &msg_send, MSG_NOSIGNAL);
+ if (res == -1 && errno == EINTR) {
+ goto retry_sendmsg;
+ }
+@@ -1150,29 +1331,30 @@
+ break; /* outgoing kernel queue full */
+ }
+ if (res == -1 && errno == EPIPE) {
+- libais_disconnect_request (conn_info);
++ disconnect_request (conn_io->conn_info);
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (0);
+ }
+ if (res == -1) {
+- assert (0);
++// assert (0);
+ break; /* some other error, stop trying to send message */
+ }
+- if (res + conn_info->byte_start != queue_item->mlen) {
+- conn_info->byte_start += res;
++ if (res + conn_io->byte_start != queue_item->mlen) {
++ conn_io->byte_start += res;
+ break;
+ }
+
+ /*
+ * Message sent, try sending another message
+ */
+- queue_item_remove (outq);
+- conn_info->byte_start = 0;
++ queue_item_remove (&conn_io->outq);
++ conn_io->byte_start = 0;
+ free (queue_item->msg);
+ } /* while queue not empty */
+
+ res = -1;
+
+- queue_empty = queue_is_empty (outq);
++ queue_empty = queue_is_empty (&conn_io->outq);
+ /*
+ * Send request message
+ */
+@@ -1181,21 +1363,19 @@
+ iov_send.iov_base = msg;
+ iov_send.iov_len = mlen;
+ retry_sendmsg_two:
+- res = sendmsg (conn_info->fd, &msg_send, MSG_NOSIGNAL);
++ res = sendmsg (conn_io->fd, &msg_send, MSG_NOSIGNAL);
+ if (res == -1 && errno == EINTR) {
+ goto retry_sendmsg_two;
+ }
+ if (res == -1 && errno == EAGAIN) {
+- conn_info->byte_start = 0;
+- conn_info->events = POLLIN|POLLNVAL;
++ conn_io->byte_start = 0;
+ }
+ if (res != -1) {
+ if (res != mlen) {
+- conn_info->byte_start += res;
++ conn_io->byte_start += res;
+ res = -1;
+ } else {
+- conn_info->byte_start = 0;
+- conn_info->events = POLLIN|POLLNVAL;
++ conn_io->byte_start = 0;
+ }
+ }
+ }
+@@ -1207,21 +1387,26 @@
+ cmsg = malloc (mlen);
+ if (cmsg == 0) {
+ log_printf (LOG_LEVEL_ERROR, "Library queue couldn't allocate a message, disconnecting library connection.\n");
+- libais_disconnect_request (conn_info);
++ disconnect_request (conn_io->conn_info);
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (-1);
+ }
+ queue_item_out.msg = cmsg;
+ queue_item_out.mlen = mlen;
+ memcpy (cmsg, msg, mlen);
+- queue_item_add (outq, &queue_item_out);
++ queue_item_add (&conn_io->outq, &queue_item_out);
+
+ /*
+- * Send a pthread_kill to interrupt the poll syscall
+- * and start a new poll operation in the thread
++ * Send a pthread_kill to interrupt the blocked poll syscall
++ * and start a new poll operation in the thread if
++ * POLLOUT is not already set
+ */
+- conn_info->events = POLLIN|POLLOUT|POLLNVAL;
+- pthread_kill (conn_info->thread, SIGUSR1);
++ if (conn_io->events != (POLLIN|POLLOUT|POLLNVAL)) {
++ conn_io->events = POLLIN|POLLOUT|POLLNVAL;
++ pthread_kill (conn_io->thread, SIGUSR1);
++ }
+ }
++ pthread_mutex_unlock (&conn_io->mutex);
+ return (0);
+ }
+
+@@ -1242,7 +1427,6 @@
+ id_len,
+ flow_control_state_set_fn,
+ context);
+- conn_info->conn_info_partner->flow_control_handle = conn_info->flow_control_handle;
+ }
+
+ void openais_ipc_flow_control_destroy (
+@@ -1283,3 +1467,18 @@
+
+ pthread_mutex_unlock (&conn_info->flow_control_mutex);
+ }
++
++
++int openais_response_send (void *conn, void *msg, int mlen)
++{
++ struct conn_info *conn_info = (struct conn_info *)conn;
++
++ return (conn_io_send (conn_info->conn_io_response, msg, mlen));
++}
++
++int openais_dispatch_send (void *conn, void *msg, int mlen)
++{
++ struct conn_info *conn_info = (struct conn_info *)conn;
++
++ return (conn_io_send (conn_info->conn_io_dispatch, msg, mlen));
++}
+diff -uNr openais-0.80.3/exec/ipc.h openais-0.80.3-r1661/exec/ipc.h
+--- openais-0.80.3/exec/ipc.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/ipc.h 2008-11-17 15:54:02.380604445 +0100
+@@ -42,17 +42,20 @@
+
+ extern int message_source_is_local (mar_message_source_t *source);
+
+-extern void *openais_conn_partner_get (void *conn);
+-
+ extern void *openais_conn_private_data_get (void *conn);
+
+-extern int openais_conn_send_response (void *conn, void *msg, int mlen);
++extern int openais_response_send (void *conn, void *msg, int mlen);
++
++extern int openais_dispatch_send (void *conn, void *msg, int mlen);
++
++extern void openais_conn_info_refcnt_dec (void *conn);
++
++extern void openais_conn_info_refcnt_inc (void *conn);
+
+ extern void openais_ipc_init (
+ void (*serialize_lock_fn) (void),
+ void (*serialize_unlock_fn) (void),
+- unsigned int gid_valid,
+- struct totem_ip_address *non_loopback_ip);
++ unsigned int gid_valid);
+
+ extern int openais_ipc_timer_add (
+ void *conn,
+diff -uNr openais-0.80.3/exec/keygen.c openais-0.80.3-r1661/exec/keygen.c
+--- openais-0.80.3/exec/keygen.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/keygen.c 2008-11-17 15:54:02.380604445 +0100
+@@ -73,7 +73,7 @@
+ /*
+ * Open key
+ */
+- authkey_fd = open ("/etc/ais/authkey", O_CREAT|O_WRONLY);
++ authkey_fd = open ("/etc/ais/authkey", O_CREAT|O_WRONLY, 600);
+ if (authkey_fd == -1) {
+ perror ("Could not create /etc/ais/authkey");
+ exit (1);
+@@ -81,7 +81,7 @@
+ /*
+ * Set security of authorization key to uid = 0 uid = 0 mode = 0400
+ */
+- fchown (authkey_fd, 0, 0);
++ res = fchown (authkey_fd, 0, 0);
+ fchmod (authkey_fd, 0400);
+
+ printf ("Writing openais key to /etc/ais/authkey.\n");
+diff -uNr openais-0.80.3/exec/lck.c openais-0.80.3-r1661/exec/lck.c
+--- openais-0.80.3/exec/lck.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/lck.c 2008-11-17 15:54:02.390605772 +0100
+@@ -719,12 +719,12 @@
+ &req_exec_lck_resourceopen->source,
+ sizeof (mar_message_source_t));
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_lck_resourceopen->source.conn,
+ &res_lib_lck_resourceopenasync,
+ sizeof (struct res_lib_lck_resourceopenasync));
+- openais_conn_send_response (
+- openais_conn_partner_get (req_exec_lck_resourceopen->source.conn),
++ openais_dispatch_send (
++ req_exec_lck_resourceopen->source.conn,
+ &res_lib_lck_resourceopenasync,
+ sizeof (struct res_lib_lck_resourceopenasync));
+ } else {
+@@ -738,7 +738,7 @@
+ &req_exec_lck_resourceopen->source,
+ sizeof (mar_message_source_t));
+
+- openais_conn_send_response (req_exec_lck_resourceopen->source.conn,
++ openais_response_send (req_exec_lck_resourceopen->source.conn,
+ &res_lib_lck_resourceopen,
+ sizeof (struct res_lib_lck_resourceopen));
+ }
+@@ -774,7 +774,7 @@
+ res_lib_lck_resourceclose.header.size = sizeof (struct res_lib_lck_resourceclose);
+ res_lib_lck_resourceclose.header.id = MESSAGE_RES_LCK_RESOURCECLOSE;
+ res_lib_lck_resourceclose.header.error = error;
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_lck_resourceclose->source.conn,
+ &res_lib_lck_resourceclose, sizeof (struct res_lib_lck_resourceclose));
+ }
+@@ -801,8 +801,8 @@
+ res_lib_lck_lockwaitercallback.mode_held = SA_LCK_PR_LOCK_MODE;
+ }
+
+- openais_conn_send_response (
+- openais_conn_partner_get (resource_lock->callback_source.conn),
++ openais_dispatch_send (
++ resource_lock->callback_source.conn,
+ &res_lib_lck_lockwaitercallback,
+ sizeof (struct res_lib_lck_lockwaitercallback));
+ }
+@@ -837,8 +837,8 @@
+ res_lib_lck_resourcelockasync.lockStatus = resource_lock->lock_status;
+ res_lib_lck_resourcelockasync.invocation = resource_lock->invocation;
+ res_lib_lck_resourcelockasync.lockId = resource_lock->lock_id;
+- openais_conn_send_response (
+- openais_conn_partner_get (source->conn),
++ openais_dispatch_send (
++ source->conn,
+ &res_lib_lck_resourcelockasync,
+ sizeof (struct res_lib_lck_resourcelockasync));
+ }
+@@ -861,7 +861,7 @@
+ res_lib_lck_resourcelock.header.error = error;
+ res_lib_lck_resourcelock.resource_lock = (void *)resource_lock;
+ res_lib_lck_resourcelock.lockStatus = resource_lock->lock_status;
+- openais_conn_send_response (source->conn,
++ openais_response_send (source->conn,
+ &res_lib_lck_resourcelock,
+ sizeof (struct res_lib_lck_resourcelock));
+ }
+@@ -1133,14 +1133,11 @@
+ * Deliver async response to library
+ */
+ req_exec_lck_resourcelock->source.conn =
+- openais_conn_partner_get (req_exec_lck_resourcelock->source.conn);
++ req_exec_lck_resourcelock->source.conn;
+ resource_lock_async_deliver (
+ &req_exec_lck_resourcelock->source,
+ resource_lock,
+ SA_AIS_OK);
+-// TODO why is this twice ?
+- req_exec_lck_resourcelock->source.conn =
+- openais_conn_partner_get (req_exec_lck_resourcelock->source.conn);
+ }
+
+ error_exit:
+@@ -1184,11 +1181,11 @@
+ res_lib_lck_resourceunlockasync.invocation =
+ req_exec_lck_resourceunlock->invocation;
+
+- openais_conn_send_response (
++ openais_dispatch_send (
+ req_exec_lck_resourceunlock->source.conn,
+ &res_lib_lck_resourceunlockasync,
+ sizeof (struct res_lib_lck_resourceunlockasync));
+- openais_conn_send_response (
++ openais_response_send (
+ resource_lock->callback_source.conn,
+ &res_lib_lck_resourceunlockasync,
+ sizeof (struct res_lib_lck_resourceunlockasync));
+@@ -1196,8 +1193,10 @@
+ res_lib_lck_resourceunlock.header.size = sizeof (struct res_lib_lck_resourceunlock);
+ res_lib_lck_resourceunlock.header.id = MESSAGE_RES_LCK_RESOURCEUNLOCK;
+ res_lib_lck_resourceunlock.header.error = error;
+- openais_conn_send_response (req_exec_lck_resourceunlock->source.conn,
+- &res_lib_lck_resourceunlock, sizeof (struct res_lib_lck_resourceunlock));
++ openais_response_send (
++ req_exec_lck_resourceunlock->source.conn,
++ &res_lib_lck_resourceunlock,
++ sizeof (struct res_lib_lck_resourceunlock));
+ }
+ }
+ }
+@@ -1253,8 +1252,10 @@
+ res_lib_lck_lockpurge.header.size = sizeof (struct res_lib_lck_lockpurge);
+ res_lib_lck_lockpurge.header.id = MESSAGE_RES_LCK_LOCKPURGE;
+ res_lib_lck_lockpurge.header.error = error;
+- openais_conn_send_response (req_exec_lck_lockpurge->source.conn,
+- &res_lib_lck_lockpurge, sizeof (struct res_lib_lck_lockpurge));
++ openais_response_send (
++ req_exec_lck_lockpurge->source.conn,
++ &res_lib_lck_lockpurge,
++ sizeof (struct res_lib_lck_lockpurge));
+ }
+ }
+
+@@ -1366,7 +1367,8 @@
+ res_lib_lck_resourceclose.header.id = MESSAGE_RES_LCK_RESOURCECLOSE;
+ res_lib_lck_resourceclose.header.error = SA_AIS_ERR_NOT_EXIST;
+
+- openais_conn_send_response (conn,
++ openais_response_send (
++ conn,
+ &res_lib_lck_resourceclose,
+ sizeof (struct res_lib_lck_resourceclose));
+ }
+diff -uNr openais-0.80.3/exec/main.c openais-0.80.3-r1661/exec/main.c
+--- openais-0.80.3/exec/main.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/main.c 2008-11-17 15:54:02.400604305 +0100
+@@ -120,8 +120,6 @@
+ }
+
+
+-struct totem_ip_address *this_ip;
+-struct totem_ip_address this_non_loopback_ip;
+ #define LOCALHOST_IP inet_addr("127.0.0.1")
+
+ totempg_groups_handle openais_group_handle;
+@@ -175,15 +173,29 @@
+ static int openais_sync_callbacks_retrieve (int sync_id,
+ struct sync_callbacks *callbacks)
+ {
+- if (ais_service[sync_id] == NULL) {
++ unsigned int ais_service_index;
++ unsigned int ais_services_found = 0;
++
++ for (ais_service_index = 0;
++ ais_service_index < SERVICE_HANDLER_MAXIMUM_COUNT;
++ ais_service_index++) {
++
++ if (ais_service[ais_service_index] != NULL) {
++ if (ais_services_found == sync_id) {
++ break;
++ }
++ ais_services_found += 1;
++ }
++ }
++ if (ais_service_index == SERVICE_HANDLER_MAXIMUM_COUNT) {
+ memset (callbacks, 0, sizeof (struct sync_callbacks));
+ return (-1);
+ }
+- callbacks->name = ais_service[sync_id]->name;
+- callbacks->sync_init = ais_service[sync_id]->sync_init;
+- callbacks->sync_process = ais_service[sync_id]->sync_process;
+- callbacks->sync_activate = ais_service[sync_id]->sync_activate;
+- callbacks->sync_abort = ais_service[sync_id]->sync_abort;
++ callbacks->name = ais_service[ais_service_index]->name;
++ callbacks->sync_init = ais_service[ais_service_index]->sync_init;
++ callbacks->sync_process = ais_service[ais_service_index]->sync_process;
++ callbacks->sync_activate = ais_service[ais_service_index]->sync_activate;
++ callbacks->sync_abort = ais_service[ais_service_index]->sync_abort;
+ return (0);
+ }
+
+@@ -200,10 +212,6 @@
+
+ memcpy (&aisexec_ring_id, ring_id, sizeof (struct memb_ring_id));
+
+- if (!totemip_localhost_check(this_ip)) {
+- totemip_copy(&this_non_loopback_ip, this_ip);
+- }
+-
+ /*
+ * Call configuration change for all services
+ */
+@@ -262,7 +270,6 @@
+
+ static void aisexec_tty_detach (void)
+ {
+-#ifndef DEBUG
+ /*
+ * Disconnect from TTY if this is not a debug run
+ */
+@@ -279,7 +286,6 @@
+ exit (0);
+ break;
+ }
+-#endif
+ }
+
+ static void aisexec_setscheduler (void)
+@@ -392,17 +398,31 @@
+ int res;
+ int totem_log_service;
+ log_init ("MAIN");
++ unsigned int background;
++ int ch;
+
+- aisexec_tty_detach ();
++ background = 1;
++
++ while ((ch = getopt (argc, argv, "fp")) != EOF) {
++ switch (ch) {
++ case 'f':
++ background = 0;
++ break;
++ default:
++ fprintf (stderr, "Usage:\n");
++ fprintf (stderr, " -f : Start application in forground.\n");
++ return EXIT_FAILURE;
++ }
++ }
++
++ if (background) {
++ aisexec_tty_detach ();
++ }
+
+ log_printf (LOG_LEVEL_NOTICE, "AIS Executive Service RELEASE '%s'\n", RELEASE_VERSION);
+ log_printf (LOG_LEVEL_NOTICE, "Copyright (C) 2002-2006 MontaVista Software, Inc and contributors.\n");
+ log_printf (LOG_LEVEL_NOTICE, "Copyright (C) 2006 Red Hat, Inc.\n");
+
+- memset(&this_non_loopback_ip, 0, sizeof(struct totem_ip_address));
+-
+- totemip_localhost(AF_INET, &this_non_loopback_ip);
+-
+ signal (SIGINT, sigintr_handler);
+ signal (SIGUSR2, sigusr2_handler);
+ signal (SIGSEGV, sigsegv_handler);
+@@ -548,8 +568,6 @@
+ /*
+ * This must occur after totempg is initialized because "this_ip" must be set
+ */
+- this_ip = &totem_config.interfaces[0].boundto;
+-
+ res = openais_service_init_all (service_count, objdb);
+ if (res == -1) {
+ log_printf (LOG_LEVEL_ERROR, "Could not init services\n");
+@@ -577,8 +595,7 @@
+ openais_ipc_init (
+ serialize_mutex_lock,
+ serialize_mutex_unlock,
+- gid_valid,
+- &this_non_loopback_ip);
++ gid_valid);
+
+ /*
+ * Start main processing loop
+diff -uNr openais-0.80.3/exec/main.h openais-0.80.3-r1661/exec/main.h
+--- openais-0.80.3/exec/main.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/main.h 2008-11-17 15:54:02.400604305 +0100
+@@ -53,8 +53,6 @@
+
+ #define SIZEINB MESSAGE_SIZE_MAX
+
+-extern struct totem_ip_address *this_ip;
+-
+ extern struct totempg_group openais_group;
+
+ extern totempg_groups_handle openais_group_handle;
+diff -uNr openais-0.80.3/exec/msg.c openais-0.80.3-r1661/exec/msg.c
+--- openais-0.80.3/exec/msg.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/msg.c 2008-11-17 15:54:02.400604305 +0100
+@@ -675,9 +675,6 @@
+ /*
+ * Initialize the saved ring ID.
+ */
+-// saved_ring_id.seq = 0;
+-// saved_ring_id.rep.s_addr = this_ip->sin_addr.s_addr;
+-
+ return (0);
+ }
+
+@@ -810,12 +807,12 @@
+ &req_exec_msg_queueopen->source,
+ sizeof (mar_message_source_t));
+
+- openais_conn_send_response (
++ openais_response_send (
+ req_exec_msg_queueopen->source.conn,
+ &res_lib_msg_queueopenasync,
+ sizeof (struct res_lib_msg_queueopenasync));
+- openais_conn_send_response (
+- openais_conn_partner_get (req_exec_msg_queueopen->source.conn),
++ openais_dispatch_send (
++ req_exec_msg_queueopen->source.conn,
+ &res_lib_msg_queueopenasync,
+ sizeof (struct res_lib_msg_queueopenasync));
+ } else {
+@@ -829,7 +826,7 @@
+ &req_exec_msg_queueopen->source,
+ sizeof (mar_message_source_t));
+
+- openais_conn_send_response (
++ openais_dispatch_send (
+ req_exec_msg_queueopen->source.conn,
+ &res_lib_msg_queueopen,
+ sizeof (struct res_lib_msg_queueopen));
+@@ -868,8 +865,10 @@
+ res_lib_msg_queueclose.header.size = sizeof (struct res_lib_msg_queueclose);
+ res_lib_msg_queueclose.header.id = MESSAGE_RES_MSG_QUEUECLOSE;
+ res_lib_msg_queueclose.header.error = error;
+- openais_conn_send_response (req_exec_msg_queueclose->source.conn,
+- &res_lib_msg_queueclose, sizeof (struct res_lib_msg_queueclose));
++ openais_dispatch_send (
++ req_exec_msg_queueclose->source.conn,
++ &res_lib_msg_queueclose,
++ sizeof (struct res_lib_msg_queueclose));
+ }
+ }
+
+@@ -930,7 +929,7 @@
+ res_lib_msg_queuegroupcreate.header.id = MESSAGE_RES_MSG_QUEUEGROUPCREATE;
+ res_lib_msg_queuegroupcreate.header.error = error;
+
+- openais_conn_send_response (
++ openais_dispatch_send (
+ req_exec_msg_queuegroupcreate->source.conn,
+ &res_lib_msg_queuegroupcreate,
+ sizeof (struct res_lib_msg_queuegroupcreate));
+@@ -977,7 +976,7 @@
+ res_lib_msg_queuegroupinsert.header.id = MESSAGE_RES_MSG_QUEUEGROUPCREATE;
+ res_lib_msg_queuegroupinsert.header.error = error;
+
+- openais_conn_send_response (
++ openais_dispatch_send (
+ req_exec_msg_queuegroupinsert->source.conn,
+ &res_lib_msg_queuegroupinsert,
+ sizeof (struct res_lib_msg_queuegroupinsert));
+@@ -1021,7 +1020,7 @@
+ res_lib_msg_queuegroupremove.header.id = MESSAGE_RES_MSG_QUEUEGROUPCREATE;
+ res_lib_msg_queuegroupremove.header.error = error;
+
+- openais_conn_send_response (
++ openais_dispatch_send (
+ req_exec_msg_queuegroupremove->source.conn,
+ &res_lib_msg_queuegroupremove,
+ sizeof (struct res_lib_msg_queuegroupremove));
+@@ -1052,7 +1051,7 @@
+ res_lib_msg_queuegroupdelete.header.id = MESSAGE_RES_MSG_QUEUEGROUPCREATE;
+ res_lib_msg_queuegroupdelete.header.error = error;
+
+- openais_conn_send_response (
++ openais_dispatch_send (
+ req_exec_msg_queuegroupdelete->source.conn,
+ &res_lib_msg_queuegroupdelete,
+ sizeof (struct res_lib_msg_queuegroupdelete));
+diff -uNr openais-0.80.3/exec/service.c openais-0.80.3-r1661/exec/service.c
+--- openais-0.80.3/exec/service.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/service.c 2008-11-17 15:54:02.380604445 +0100
+@@ -87,7 +87,7 @@
+ }
+ };
+
+-struct openais_service_handler *ais_service[128];
++struct openais_service_handler *ais_service[SERVICE_HANDLER_MAXIMUM_COUNT];
+
+ /*
+ * Adds a service handler to the object database
+diff -uNr openais-0.80.3/exec/service.h openais-0.80.3-r1661/exec/service.h
+--- openais-0.80.3/exec/service.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/service.h 2008-11-17 15:54:02.380604445 +0100
+@@ -44,6 +44,7 @@
+ #endif
+
+ #define SERVICE_ID_MAKE(a,b) ( ((a)<<16) | (b) )
++#define SERVICE_HANDLER_MAXIMUM_COUNT 64
+
+ enum openais_flow_control {
+ OPENAIS_FLOW_CONTROL_REQUIRED = 1,
+diff -uNr openais-0.80.3/exec/sync.c openais-0.80.3-r1661/exec/sync.c
+--- openais-0.80.3/exec/sync.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/sync.c 2008-11-17 15:54:02.390605772 +0100
+@@ -198,9 +198,10 @@
+ {
+ int res;
+
+-// TODO rewrite this to get rid of the for (;;)
+ for (;;) {
+- res = sync_callbacks_retrieve (sync_recovery_index, &sync_callbacks);
++ res = sync_callbacks_retrieve (sync_recovery_index,
++ &sync_callbacks);
++
+ /*
+ * No more service handlers have sync callbacks at this time
+ ` */
+@@ -418,7 +419,6 @@
+ log_printf (LOG_LEVEL_DEBUG,
+ "Committing synchronization for (%s)\n",
+ sync_callbacks.name);
+-
+ }
+
+ /*
+@@ -452,8 +452,12 @@
+ {
+ sync_ring_id = ring_id;
+
++ if (configuration_type != TOTEM_CONFIGURATION_REGULAR) {
++ return;
++ }
+ if (sync_processing && sync_callbacks.sync_abort != NULL) {
+ sync_callbacks.sync_abort ();
++ sync_callbacks.sync_activate = NULL;
+ }
+ /*
+ * If no virtual synchrony filter configured, then start
+diff -uNr openais-0.80.3/exec/timer.c openais-0.80.3-r1661/exec/timer.c
+--- openais-0.80.3/exec/timer.c 2007-06-25 04:22:54.000000000 +0200
++++ openais-0.80.3-r1661/exec/timer.c 2008-11-17 15:54:02.400604305 +0100
+@@ -126,13 +126,13 @@
+ if (fds == -1) {
+ goto retry_poll;
+ }
+- pthread_mutex_lock (&timer_mutex);
+ timer_serialize_lock_fn ();
++ pthread_mutex_lock (&timer_mutex);
+
+ timerlist_expire (&timers_timerlist);
+
+- timer_serialize_unlock_fn ();
+ pthread_mutex_unlock (&timer_mutex);
++ timer_serialize_unlock_fn ();
+ }
+
+ pthread_exit (0);
+@@ -177,7 +177,7 @@
+ int res;
+ int unlock;
+
+- if (pthread_equal (pthread_self(), expiry_thread) == 0) {
++ if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+ unlock = 0;
+ } else {
+ unlock = 1;
+@@ -209,7 +209,7 @@
+ int res;
+ int unlock;
+
+- if (pthread_equal (pthread_self(), expiry_thread) == 0) {
++ if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+ unlock = 0;
+ } else {
+ unlock = 1;
+@@ -241,7 +241,7 @@
+ return;
+ }
+
+- if (pthread_equal (pthread_self(), expiry_thread) == 0) {
++ if (pthread_equal (pthread_self(), expiry_thread) != 0) {
+ unlock = 0;
+ } else {
+ unlock = 1;
+diff -uNr openais-0.80.3/exec/totem.h openais-0.80.3-r1661/exec/totem.h
+--- openais-0.80.3/exec/totem.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totem.h 2008-11-17 15:54:02.400604305 +0100
+@@ -89,6 +89,7 @@
+ struct totem_interface *interfaces;
+ int interface_count;
+ unsigned int node_id;
++ unsigned int clear_node_high_bit;
+
+ /*
+ * key information
+diff -uNr openais-0.80.3/exec/totemconfig.c openais-0.80.3-r1661/exec/totemconfig.c
+--- openais-0.80.3/exec/totemconfig.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totemconfig.c 2008-11-17 15:54:02.400604305 +0100
+@@ -174,6 +174,13 @@
+ */
+ objdb_get_int (objdb, object_totem_handle, "nodeid", &totem_config->node_id);
+
++ totem_config->clear_node_high_bit = 0;
++ if (!objdb_get_string (objdb,object_totem_handle, "clear_node_high_bit", &str)) {
++ if (strcmp (str, "yes") == 0) {
++ totem_config->clear_node_high_bit = 1;
++ }
++ }
++
+ objdb_get_int (objdb,object_totem_handle, "threads", &totem_config->threads);
+
+
+diff -uNr openais-0.80.3/exec/totemmrp.c openais-0.80.3-r1661/exec/totemmrp.c
+--- openais-0.80.3/exec/totemmrp.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totemmrp.c 2008-11-17 15:54:02.390605772 +0100
+@@ -191,6 +191,16 @@
+ return (res);
+ }
+
++int totemmrp_my_nodeid_get (void)
++{
++ return (totemsrp_my_nodeid_get (totemsrp_handle_in));
++}
++
++int totemmrp_my_family_get (void)
++{
++ return (totemsrp_my_family_get (totemsrp_handle_in));
++}
++
+ extern int totemmrp_ring_reenable (void)
+ {
+ int res;
+diff -uNr openais-0.80.3/exec/totemmrp.h openais-0.80.3-r1661/exec/totemmrp.h
+--- openais-0.80.3/exec/totemmrp.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totemmrp.h 2008-11-17 15:54:02.390605772 +0100
+@@ -105,6 +105,10 @@
+ char ***status,
+ unsigned int *iface_count);
+
++extern int totemmrp_my_nodeid_get (void);
++
++extern int totemmrp_my_family_get (void);
++
+ extern int totemmrp_ring_reenable (void);
+
+ #endif /* TOTEMMRP_H_DEFINED */
+diff -uNr openais-0.80.3/exec/totemnet.c openais-0.80.3-r1661/exec/totemnet.c
+--- openais-0.80.3/exec/totemnet.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totemnet.c 2008-11-17 15:54:02.370604375 +0100
+@@ -1227,6 +1227,15 @@
+
+ instance->totemnet_poll_handle = poll_handle;
+
++ if(instance->totem_config->node_id == 0) {
++ int32_t nodeid = 0;
++ memcpy (&nodeid, instance->totem_interface->bindnet.addr, sizeof (int32_t));
++ if(nodeid < 0 && instance->totem_config->clear_node_high_bit) {
++ nodeid = 0 - nodeid;
++ }
++ instance->totem_config->node_id = nodeid;
++ }
++
+ instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
+
+ instance->context = context;
+diff -uNr openais-0.80.3/exec/totempg.c openais-0.80.3-r1661/exec/totempg.c
+--- openais-0.80.3/exec/totempg.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totempg.c 2008-11-17 15:54:02.380604445 +0100
+@@ -720,14 +720,16 @@
+ * Multicast a message
+ */
+ static int mcast_msg (
+- struct iovec *iovec,
++ struct iovec *iovec_in,
+ int iov_len,
+ int guarantee)
+ {
+ int res = 0;
+ struct totempg_mcast mcast;
+ struct iovec iovecs[3];
++ struct iovec iovec[64];
+ int i;
++ int dest, src;
+ int max_packet_size = 0;
+ int copy_len = 0;
+ int copy_base = 0;
+@@ -736,6 +738,18 @@
+ pthread_mutex_lock (&mcast_msg_mutex);
+ totemmrp_new_msg_signal ();
+
++ /*
++ * Remove zero length iovectors from the list
++ */
++ assert (iov_len < 64);
++ for (dest = 0, src = 0; src < iov_len; src++) {
++ if (iovec_in[src].iov_len) {
++ memcpy (&iovec[dest++], &iovec_in[src],
++ sizeof (struct iovec));
++ }
++ }
++ iov_len = dest;
++
+ max_packet_size = TOTEMPG_PACKET_SIZE -
+ (sizeof (unsigned short) * (mcast_packed_msg_count + 1));
+
+@@ -870,13 +884,14 @@
+ /*
+ * Determine if a message of msg_size could be queued
+ */
++#define FUZZY_AVAIL_SUBTRACT 5
+ static int send_ok (
+ int msg_size)
+ {
+ int avail = 0;
+ int total;
+
+- avail = totemmrp_avail ();
++ avail = totemmrp_avail () - FUZZY_AVAIL_SUBTRACT;
+
+ /*
+ * msg size less then totempg_totem_config->net_mtu - 25 will take up
+@@ -1241,3 +1256,12 @@
+ return (iface_string);
+ }
+
++int totempg_my_nodeid_get (void)
++{
++ return (totemmrp_my_nodeid_get());
++}
++
++int totempg_my_family_get (void)
++{
++ return (totemmrp_my_family_get());
++}
+diff -uNr openais-0.80.3/exec/totempg.h openais-0.80.3-r1661/exec/totempg.h
+--- openais-0.80.3/exec/totempg.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totempg.h 2008-11-17 15:54:02.380604445 +0100
+@@ -137,8 +137,12 @@
+ char ***status,
+ unsigned int *iface_count);
+
+-extern int totempg_ring_reenable (void);
+-
+ extern char *totempg_ifaces_print (unsigned int nodeid);
+
++extern int totempg_my_nodeid_get (void);
++
++extern int totempg_my_family_get (void);
++
++extern int totempg_ring_reenable (void);
++
+ #endif /* TOTEMPG_H_DEFINED */
+diff -uNr openais-0.80.3/exec/totemsrp.c openais-0.80.3-r1661/exec/totemsrp.c
+--- openais-0.80.3/exec/totemsrp.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totemsrp.c 2008-11-17 15:54:02.400604305 +0100
+@@ -138,6 +138,11 @@
+ MESSAGE_TYPE_TOKEN_HOLD_CANCEL = 5, /* cancel the holding of the token */
+ };
+
++enum encapsulation_type {
++ MESSAGE_ENCAPSULATED = 1,
++ MESSAGE_NOT_ENCAPSULATED = 2
++};
++
+ /*
+ * New membership algorithm local variables
+ */
+@@ -393,8 +398,6 @@
+
+ unsigned int my_token_seq;
+
+- unsigned int my_commit_token_seq;
+-
+ /*
+ * Timers
+ */
+@@ -551,7 +554,8 @@
+ int fcc_mcasts_allowed);
+ static void messages_free (struct totemsrp_instance *instance, unsigned int token_aru);
+
+-static void memb_ring_id_store (struct totemsrp_instance *instance);
++static void memb_ring_id_set_and_store (struct totemsrp_instance *instance,
++ struct memb_ring_id *ring_id);
+ static void memb_state_commit_token_update (struct totemsrp_instance *instance, struct memb_commit_token *commit_token);
+ static void memb_state_commit_token_target_set (struct totemsrp_instance *instance, struct memb_commit_token *commit_token);
+ static int memb_state_commit_token_send (struct totemsrp_instance *instance, struct memb_commit_token *memb_commit_token);
+@@ -615,12 +619,10 @@
+
+ list_init (&instance->token_callback_sent_listhead);
+
+- instance->my_received_flg = 0;
++ instance->my_received_flg = 1;
+
+ instance->my_token_seq = SEQNO_START_TOKEN - 1;
+
+- instance->my_commit_token_seq = SEQNO_START_TOKEN - 1;
+-
+ instance->memb_state = MEMB_STATE_OPERATIONAL;
+
+ instance->set_aru = -1;
+@@ -903,6 +905,43 @@
+ return (res);
+ }
+
++int totemsrp_my_nodeid_get (
++ totemsrp_handle handle)
++{
++ struct totemsrp_instance *instance;
++ int res;
++
++ res = hdb_handle_get (&totemsrp_instance_database, handle,
++ (void *)&instance);
++ if (res != 0) {
++ return (0);
++ }
++
++ res = instance->totem_config->interfaces[0].boundto.nodeid;
++
++ hdb_handle_put (&totemsrp_instance_database, handle);
++ return (res);
++}
++
++int totemsrp_my_family_get (
++ totemsrp_handle handle)
++{
++ struct totemsrp_instance *instance;
++ int res;
++
++ res = hdb_handle_get (&totemsrp_instance_database, handle,
++ (void *)&instance);
++ if (res != 0) {
++ return (0);
++ }
++
++ res = instance->totem_config->interfaces[0].boundto.family;
++
++ hdb_handle_put (&totemsrp_instance_database, handle);
++ return (res);
++}
++
++
+ int totemsrp_ring_reenable (
+ totemsrp_handle handle)
+ {
+@@ -1552,6 +1591,8 @@
+ unsigned int new_memb_list_totemip[PROCESSOR_COUNT_MAX];
+ unsigned int left_list[PROCESSOR_COUNT_MAX];
+
++ memb_consensus_reset (instance);
++
+ old_ring_state_reset (instance);
+ ring_reset (instance);
+ deliver_messages_from_recovery_to_regular (instance);
+@@ -1637,7 +1678,7 @@
+ "entering OPERATIONAL state.\n");
+ instance->memb_state = MEMB_STATE_OPERATIONAL;
+
+- instance->my_received_flg = 0;
++ instance->my_received_flg = 1;
+
+ return;
+ }
+@@ -1646,8 +1687,6 @@
+ struct totemsrp_instance *instance,
+ int gather_from)
+ {
+- instance->my_commit_token_seq = SEQNO_START_TOKEN - 1;
+-
+ memb_set_merge (
+ &instance->my_id, 1,
+ instance->my_proc_list, &instance->my_proc_list_entries);
+@@ -1711,10 +1750,10 @@
+
+ memb_state_commit_token_target_set (instance, commit_token);
+
++ memb_ring_id_set_and_store (instance, &commit_token->ring_id);
++
+ memb_state_commit_token_send (instance, commit_token);
+
+- memcpy (&instance->my_ring_id, &commit_token->ring_id,
+- sizeof (struct memb_ring_id));
+ instance->token_ring_id_seq = instance->my_ring_id.seq;
+
+ poll_timer_delete (instance->totemsrp_poll_handle, instance->memb_timer_state_gather_join_timeout);
+@@ -1733,8 +1772,6 @@
+
+ instance->memb_state = MEMB_STATE_COMMIT;
+
+- instance->my_commit_token_seq = SEQNO_START_TOKEN - 1;
+-
+ /*
+ * reset all flow control variables since we are starting a new ring
+ */
+@@ -1779,15 +1816,10 @@
+ /*
+ * Build regular configuration
+ */
+- instance->my_new_memb_entries = commit_token->addr_entries;
+-
+ totemrrp_processor_count_set (
+ instance->totemrrp_handle,
+ commit_token->addr_entries);
+
+- memcpy (instance->my_new_memb_list, addr,
+- sizeof (struct srp_addr) * instance->my_new_memb_entries);
+-
+ /*
+ * Build transitional configuration
+ */
+@@ -1892,13 +1924,14 @@
+ // TODO LEAK
+ message_item.mcast = malloc (sizeof (struct mcast));
+ assert (message_item.mcast);
+- memcpy (message_item.mcast, sort_queue_item->iovec[0].iov_base,
+- sizeof (struct mcast));
+- memcpy (&message_item.mcast->ring_id, &instance->my_ring_id,
+- sizeof (struct memb_ring_id));
+- message_item.mcast->header.encapsulated = 1;
++ message_item.mcast->header.type = MESSAGE_TYPE_MCAST;
++ srp_addr_copy (&message_item.mcast->system_from, &instance->my_id);
++ message_item.mcast->header.encapsulated = MESSAGE_ENCAPSULATED;
+ message_item.mcast->header.nodeid = instance->my_id.addr[0].nodeid;
+ assert (message_item.mcast->header.nodeid);
++ message_item.mcast->header.endian_detector = ENDIAN_LOCAL;
++ memcpy (&message_item.mcast->ring_id, &instance->my_ring_id,
++ sizeof (struct memb_ring_id));
+ message_item.iov_len = sort_queue_item->iov_len;
+ memcpy (&message_item.iovec, &sort_queue_item->iovec,
+ sizeof (struct iovec) * sort_queue_item->iov_len);
+@@ -1926,7 +1959,6 @@
+
+ reset_token_timeout (instance); // REVIEWED
+ reset_token_retransmit_timeout (instance); // REVIEWED
+- memb_ring_id_store (instance);
+
+ instance->memb_state = MEMB_STATE_RECOVERY;
+ return;
+@@ -1993,7 +2025,7 @@
+ */
+ message_item.mcast->header.type = MESSAGE_TYPE_MCAST;
+ message_item.mcast->header.endian_detector = ENDIAN_LOCAL;
+- message_item.mcast->header.encapsulated = 2;
++ message_item.mcast->header.encapsulated = MESSAGE_NOT_ENCAPSULATED;
+ message_item.mcast->header.nodeid = instance->my_id.addr[0].nodeid;
+ assert (message_item.mcast->header.nodeid);
+
+@@ -2278,13 +2310,13 @@
+ * Delete item from pending queue
+ */
+ queue_item_remove (mcast_queue);
++
++ /*
++ * If messages mcasted, deliver any new messages to totempg
++ */
++ instance->my_high_seq_received = token->seq;
+ }
+
+- /*
+- * If messages mcasted, deliver any new messages to totempg
+- */
+- instance->my_high_seq_received = token->seq;
+-
+ update_aru (instance);
+
+ /*
+@@ -2564,14 +2596,14 @@
+ orf_token.token_seq = SEQNO_START_TOKEN;
+ orf_token.retrans_flg = 1;
+ instance->my_set_retrans_flg = 1;
+-/*
++
+ if (queue_is_empty (&instance->retrans_message_queue) == 1) {
+ orf_token.retrans_flg = 0;
++ instance->my_set_retrans_flg = 0;
+ } else {
+ orf_token.retrans_flg = 1;
+ instance->my_set_retrans_flg = 1;
+ }
+-*/
+
+ orf_token.aru = 0;
+ orf_token.aru = SEQNO_START_MSG - 1;
+@@ -2594,10 +2626,17 @@
+ {
+ struct srp_addr *addr;
+ struct memb_commit_token_memb_entry *memb_list;
++ unsigned int high_aru;
++ unsigned int i;
+
+ addr = (struct srp_addr *)commit_token->end_of_commit_token;
+ memb_list = (struct memb_commit_token_memb_entry *)(addr + commit_token->addr_entries);
+
++ memcpy (instance->my_new_memb_list, addr,
++ sizeof (struct srp_addr) * commit_token->addr_entries);
++
++ instance->my_new_memb_entries = commit_token->addr_entries;
++
+ memcpy (&memb_list[commit_token->memb_index].ring_id,
+ &instance->my_old_ring_id, sizeof (struct memb_ring_id));
+ assert (!totemip_zero_check(&instance->my_old_ring_id.rep));
+@@ -2607,9 +2646,43 @@
+ * TODO high delivered is really instance->my_aru, but with safe this
+ * could change?
+ */
+- memb_list[commit_token->memb_index].high_delivered = instance->my_high_delivered;
++ instance->my_received_flg =
++ (instance->my_aru == instance->my_high_seq_received);
++
+ memb_list[commit_token->memb_index].received_flg = instance->my_received_flg;
+
++ memb_list[commit_token->memb_index].high_delivered = instance->my_high_delivered;
++ /*
++ * find high aru up to current memb_index for all matching ring ids
++ * if any ring id matching memb_index has aru less then high aru set
++ * received flag for that entry to false
++ */
++ high_aru = memb_list[commit_token->memb_index].aru;
++ for (i = 0; i <= commit_token->memb_index; i++) {
++ if (memcmp (&memb_list[commit_token->memb_index].ring_id,
++ &memb_list[i].ring_id,
++ sizeof (struct memb_ring_id)) == 0) {
++
++ if (sq_lt_compare (high_aru, memb_list[i].aru)) {
++ high_aru = memb_list[i].aru;
++ }
++ }
++ }
++
++ for (i = 0; i <= commit_token->memb_index; i++) {
++ if (memcmp (&memb_list[commit_token->memb_index].ring_id,
++ &memb_list[i].ring_id,
++ sizeof (struct memb_ring_id)) == 0) {
++
++ if (sq_lt_compare (memb_list[i].aru, high_aru)) {
++ memb_list[i].received_flg = 0;
++ if (i == commit_token->memb_index) {
++ instance->my_received_flg = 0;
++ }
++ }
++ }
++ }
++
+ commit_token->header.nodeid = instance->my_id.addr[0].nodeid;
+ commit_token->memb_index += 1;
+ assert (commit_token->memb_index <= commit_token->addr_entries);
+@@ -2773,7 +2846,7 @@
+ iovs = 2;
+ } else {
+ iovs = 3;
+- iovec[2].iov_base = &instance->my_failed_list;
++ iovec[2].iov_base = instance->my_failed_list;
+ iovec[2].iov_len = instance->my_failed_list_entries *
+ sizeof (struct srp_addr);
+ }
+@@ -2846,13 +2919,16 @@
+ instance->token_ring_id_seq = memb_ring_id->seq;
+ }
+
+-static void memb_ring_id_store (
+- struct totemsrp_instance *instance)
++static void memb_ring_id_set_and_store (
++ struct totemsrp_instance *instance,
++ struct memb_ring_id *ring_id)
+ {
+ char filename[256];
+ int fd;
+ int res;
+
++ memcpy (&instance->my_ring_id, ring_id, sizeof (struct memb_ring_id));
++
+ sprintf (filename, "%s/ringid_%s",
+ rundir, totemip_print (&instance->my_id.addr[0]));
+
+@@ -3085,7 +3161,6 @@
+ unsigned int mcasted_retransmit;
+ unsigned int mcasted_regular;
+ unsigned int last_aru;
+- unsigned int low_water;
+
+ #ifdef GIVEINFO
+ struct timeval tv_current;
+@@ -3279,13 +3354,7 @@
+ * has recovered all messages it can recover
+ * (ie: its retrans queue is empty)
+ */
+- low_water = instance->my_aru;
+- if (sq_lt_compare (last_aru, low_water)) {
+- low_water = last_aru;
+- }
+-// TODO is this code right
+- if (queue_is_empty (&instance->retrans_message_queue) == 0 ||
+- low_water != instance->my_high_seq_received) {
++ if (queue_is_empty (&instance->retrans_message_queue) == 0) {
+
+ if (token->retrans_flg == 0) {
+ token->retrans_flg = 1;
+@@ -3296,10 +3365,10 @@
+ token->retrans_flg = 0;
+ }
+ log_printf (instance->totemsrp_log_level_debug,
+- "token retrans flag is %d my set retrans flag%d retrans queue empty %d count %d, low_water %x aru %x\n",
++ "token retrans flag is %d my set retrans flag%d retrans queue empty %d count %d, aru %x\n",
+ token->retrans_flg, instance->my_set_retrans_flg,
+ queue_is_empty (&instance->retrans_message_queue),
+- instance->my_retrans_flg_count, low_water, token->aru);
++ instance->my_retrans_flg_count, token->aru);
+ if (token->retrans_flg == 0) {
+ instance->my_retrans_flg_count += 1;
+ } else {
+@@ -3311,13 +3380,16 @@
+ log_printf (instance->totemsrp_log_level_debug,
+ "install seq %x aru %x high seq received %x\n",
+ instance->my_install_seq, instance->my_aru, instance->my_high_seq_received);
+- if (instance->my_retrans_flg_count >= 2 && instance->my_aru >= instance->my_install_seq && instance->my_received_flg == 0) {
++ if (instance->my_retrans_flg_count >= 2 &&
++ instance->my_received_flg == 0 &&
++ sq_lte_compare (instance->my_install_seq, instance->my_aru)) {
+ instance->my_received_flg = 1;
+ instance->my_deliver_memb_entries = instance->my_trans_memb_entries;
+ memcpy (instance->my_deliver_memb_list, instance->my_trans_memb_list,
+ sizeof (struct totem_ip_address) * instance->my_trans_memb_entries);
+ }
+- if (instance->my_retrans_flg_count >= 3 && token->aru >= instance->my_install_seq) {
++ if (instance->my_retrans_flg_count >= 3 &&
++ sq_lte_compare (instance->my_install_seq, token->aru)) {
+ instance->my_rotation_counter += 1;
+ } else {
+ instance->my_rotation_counter = 0;
+@@ -3386,9 +3458,10 @@
+ struct sort_queue_item *sort_queue_item_p;
+ unsigned int i;
+ int res;
+- struct mcast *mcast;
++ struct mcast *mcast_in;
++ struct mcast mcast_header;
+ unsigned int range = 0;
+- int endian_conversion_required = 0 ;
++ int endian_conversion_required;
+ unsigned int my_high_delivered_stored = 0;
+
+
+@@ -3436,18 +3509,27 @@
+
+ sort_queue_item_p = ptr;
+
+- mcast = sort_queue_item_p->iovec[0].iov_base;
+- assert (mcast != (struct mcast *)0xdeadbeef);
++ mcast_in = sort_queue_item_p->iovec[0].iov_base;
++ assert (mcast_in != (struct mcast *)0xdeadbeef);
++
++ endian_conversion_required = 0;
++ if (mcast_in->header.endian_detector != ENDIAN_LOCAL) {
++ endian_conversion_required = 1;
++ mcast_endian_convert (mcast_in, &mcast_header);
++ } else {
++ memcpy (&mcast_header, mcast_in, sizeof (struct mcast));
++ }
+
+ /*
+ * Skip messages not originated in instance->my_deliver_memb
+ */
+ if (skip &&
+- memb_set_subset (&mcast->system_from,
++ memb_set_subset (&mcast_header.system_from,
+ 1,
+ instance->my_deliver_memb_list,
+ instance->my_deliver_memb_entries) == 0) {
+- instance->my_high_delivered = my_high_delivered_stored + i;
++
++ instance->my_high_delivered = my_high_delivered_stored + i;
+
+ continue;
+ }
+@@ -3457,12 +3539,7 @@
+ */
+ log_printf (instance->totemsrp_log_level_debug,
+ "Delivering MCAST message with seq %x to pending delivery queue\n",
+- mcast->seq);
+-
+- if (mcast->header.endian_detector != ENDIAN_LOCAL) {
+- endian_conversion_required = 1;
+- mcast_endian_convert (mcast, mcast);
+- }
++ mcast_header.seq);
+
+ /*
+ * Message is locally originated multicast
+@@ -3470,7 +3547,7 @@
+ if (sort_queue_item_p->iov_len > 1 &&
+ sort_queue_item_p->iovec[0].iov_len == sizeof (struct mcast)) {
+ instance->totemsrp_deliver_fn (
+- mcast->header.nodeid,
++ mcast_header.header.nodeid,
+ &sort_queue_item_p->iovec[1],
+ sort_queue_item_p->iov_len - 1,
+ endian_conversion_required);
+@@ -3479,7 +3556,7 @@
+ sort_queue_item_p->iovec[0].iov_base += sizeof (struct mcast);
+
+ instance->totemsrp_deliver_fn (
+- mcast->header.nodeid,
++ mcast_header.header.nodeid,
+ sort_queue_item_p->iovec,
+ sort_queue_item_p->iov_len,
+ endian_conversion_required);
+@@ -3511,18 +3588,12 @@
+ memcpy (&mcast_header, msg, sizeof (struct mcast));
+ }
+
+-/*
+- if (mcast_header.header.encapsulated == 1) {
+- sort_queue = &instance->recovery_sort_queue;
+- } else {
+- sort_queue = &instance->regular_sort_queue;
+- }
+-*/
+- if (instance->memb_state == MEMB_STATE_RECOVERY) {
++ if (mcast_header.header.encapsulated == MESSAGE_ENCAPSULATED) {
+ sort_queue = &instance->recovery_sort_queue;
+ } else {
+ sort_queue = &instance->regular_sort_queue;
+ }
++
+ assert (msg_len < FRAME_SIZE_MAX);
+
+ #ifdef TEST_DROP_MCAST_PERCENTAGE
+@@ -3849,6 +3920,8 @@
+ out->header.type = in->header.type;
+ out->header.endian_detector = ENDIAN_LOCAL;
+ out->header.nodeid = swab32 (in->header.nodeid);
++ out->header.encapsulated = in->header.encapsulated;
++
+ out->seq = swab32 (in->seq);
+ out->this_seqno = swab32 (in->this_seqno);
+ totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
+@@ -3961,16 +4034,6 @@
+ addr = (struct srp_addr *)memb_commit_token->end_of_commit_token;
+ memb_list = (struct memb_commit_token_memb_entry *)(addr + memb_commit_token->addr_entries);
+
+- if (sq_lte_compare (memb_commit_token->token_seq,
+- instance->my_commit_token_seq)) {
+- /*
+- * discard token
+- */
+- return (0);
+- }
+- instance->my_commit_token_seq = memb_commit_token->token_seq;
+-
+-
+ #ifdef TEST_DROP_COMMIT_TOKEN_PERCENTAGE
+ if (random()%100 < TEST_DROP_COMMIT_TOKEN_PERCENTAGE) {
+ return (0);
+@@ -3998,9 +4061,15 @@
+ break;
+
+ case MEMB_STATE_COMMIT:
+-// if (memcmp (&memb_commit_token->ring_id, &instance->my_ring_id,
+-// sizeof (struct memb_ring_id)) == 0) {
+- if (memb_commit_token->ring_id.seq == instance->my_ring_id.seq) {
++ /*
++ * If retransmitted commit tokens are sent on this ring
++ * filter them out and only enter recovery once the
++ * commit token has traversed the array. This is
++ * determined by :
++ * memb_commit_token->memb_index == memb_commit_token->addr_entries) {
++ */
++ if (memb_commit_token->ring_id.seq == instance->my_ring_id.seq &&
++ memb_commit_token->memb_index == memb_commit_token->addr_entries) {
+ memb_state_recovery_enter (instance, memb_commit_token);
+ }
+ break;
+@@ -4051,7 +4120,12 @@
+ log_printf (instance->totemsrp_log_level_security, "Received message is too short... ignoring %d.\n", msg_len);
+ return;
+ }
+-
++
++ if ((int)message_header->type >= totemsrp_message_handlers.count) {
++ log_printf (instance->totemsrp_log_level_security, "Type of received message is wrong... ignoring %d.\n", (int)message_header->type);
++ return;
++ }
++
+ /*
+ * Handle incoming message
+ */
+diff -uNr openais-0.80.3/exec/totemsrp.h openais-0.80.3-r1661/exec/totemsrp.h
+--- openais-0.80.3/exec/totemsrp.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/totemsrp.h 2008-11-17 15:54:02.400604305 +0100
+@@ -104,6 +104,12 @@
+ char ***status,
+ unsigned int *iface_count);
+
++extern int totemsrp_my_nodeid_get (
++ totemsrp_handle handle);
++
++extern int totemsrp_my_family_get (
++ totemsrp_handle handle);
++
+ extern int totemsrp_ring_reenable (
+ totemsrp_handle handle);
+
+diff -uNr openais-0.80.3/exec/util.c openais-0.80.3-r1661/exec/util.c
+--- openais-0.80.3/exec/util.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/util.c 2008-11-17 15:54:02.380604445 +0100
+@@ -84,10 +84,88 @@
+ return time_now;
+ }
+
++struct error_code_entry {
++ enum e_ais_done code;
++ char *string;
++};
++
++static struct error_code_entry error_code_map[] = {
++ {
++ .code = AIS_DONE_EXIT,
++ .string = "finished, exiting normally"
++ },
++ {
++ .code = AIS_DONE_UID_DETERMINE,
++ .string = "could not determine the process UID"
++ },
++ {
++ .code = AIS_DONE_GID_DETERMINE,
++ .string = "could not determine the process GID"
++ },
++ {
++ .code = AIS_DONE_MEMPOOL_INIT,
++ .string = "could not initialize the memory pools"
++ },
++ {
++ .code = AIS_DONE_FORK,
++ .string = "could not fork"
++ },
++ {
++ .code = AIS_DONE_LIBAIS_SOCKET,
++ .string = "could not create a socket"
++ },
++ {
++ .code = AIS_DONE_LIBAIS_BIND,
++ .string = "could not bind to an address"
++ },
++ {
++ .code = AIS_DONE_READKEY,
++ .string = "could not read the security key"
++ },
++ {
++ .code = AIS_DONE_MAINCONFIGREAD,
++ .string = "could not read the main configuration file"
++ },
++ {
++ .code = AIS_DONE_LOGSETUP,
++ .string = "could not setup the logging system"
++ },
++ {
++ .code = AIS_DONE_AMFCONFIGREAD,
++ .string = "could not read the AMF configuration"
++ },
++ {
++ .code = AIS_DONE_DYNAMICLOAD,
++ .string = "could not load a dynamic object"
++ },
++ { .code = AIS_DONE_OBJDB,
++ .string = "could not use the object database"
++ },
++ {
++ .code = AIS_DONE_INIT_SERVICES,
++ .string = "could not initlalize services"
++ },
++ {
++ .code = AIS_DONE_OUT_OF_MEMORY,
++ .string = "Out of memory"
++ },
++ {
++ .code = AIS_DONE_FATAL_ERR,
++ .string = "Unknown fatal error"
++ },
++};
+
+ void openais_exit_error (enum e_ais_done err)
+ {
+- log_printf (LOG_LEVEL_ERROR, "AIS Executive exiting (%d).\n", err);
++ char *error_string = "Error code not available";
++ int i;
++
++ for (i = 0; i < (sizeof (error_code_map) / sizeof (struct error_code_entry)); i++) {
++ if (err == error_code_map[i].code) {
++ error_string = error_code_map[i].string;
++ }
++ }
++ log_printf (LOG_LEVEL_ERROR, "AIS Executive exiting (reason: %s).\n", error_string);
+ log_flush();
+ exit (err);
+ }
+diff -uNr openais-0.80.3/exec/version.h openais-0.80.3-r1661/exec/version.h
+--- openais-0.80.3/exec/version.h 2007-06-26 13:36:38.000000000 +0200
++++ openais-0.80.3-r1661/exec/version.h 2008-11-17 15:54:02.380604445 +0100
+@@ -1 +1 @@
+-#define RELEASE_VERSION "subrev 1358 version 0.80.3"
++#define RELEASE_VERSION "subrev 1152 version 0.80"
+diff -uNr openais-0.80.3/exec/vsf_ykd.c openais-0.80.3-r1661/exec/vsf_ykd.c
+--- openais-0.80.3/exec/vsf_ykd.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/exec/vsf_ykd.c 2008-11-17 15:54:02.390605772 +0100
+@@ -458,7 +458,7 @@
+ memcpy (&ykd_ring_id, ring_id, sizeof (struct memb_ring_id));
+
+ if (first_run) {
+- ykd_state.last_primary.member_list[0] = this_ip->nodeid;
++ ykd_state.last_primary.member_list[0] = totempg_my_nodeid_get();
+ ykd_state.last_primary.member_list_entries = 1;
+ ykd_state.last_primary.session_id = 0;
+ first_run = 0;
+diff -uNr openais-0.80.3/include/saCkpt.h openais-0.80.3-r1661/include/saCkpt.h
+--- openais-0.80.3/include/saCkpt.h 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/include/saCkpt.h 2008-11-17 15:54:00.450629028 +0100
+@@ -199,7 +199,7 @@
+ SaCkptCheckpointHandleT checkpointHandle,
+ SaCkptSectionCreationAttributesT *sectionCreationAttributes,
+ const void *initialData,
+- SaUint32T initialDataSize);
++ SaSizeT initialDataSize);
+
+
+ SaAisErrorT
+diff -uNr openais-0.80.3/init/redhat openais-0.80.3-r1661/init/redhat
+--- openais-0.80.3/init/redhat 2007-06-26 13:38:35.000000000 +0200
++++ openais-0.80.3-r1661/init/redhat 2008-11-17 15:54:02.790606471 +0100
+@@ -15,6 +15,7 @@
+ lockfile="/var/lock/subsys/$prog"
+
+ start() {
++ [ -x "$exec" ] || exit 5
+ echo -n $"Starting OpenAIS daemon ($prog): "
+ daemon $exec
+ retval=$?
+diff -uNr openais-0.80.3/lcr/Makefile openais-0.80.3-r1661/lcr/Makefile
+--- openais-0.80.3/lcr/Makefile 2006-04-21 01:17:16.000000000 +0200
++++ openais-0.80.3-r1661/lcr/Makefile 2008-11-17 15:53:59.910615969 +0100
+@@ -27,7 +27,7 @@
+ include ../Makefile.inc
+
+ CFLAGS += -I../include
+-LDFLAGS += -L./ ${DYFLAGS}
++override LDFLAGS += ${DYFLAGS}
+
+ ifeq (${OPENAIS_COMPAT}, LINUX)
+ LDFLAGS += -ldl
+@@ -57,7 +57,7 @@
+ endif
+
+ test: test.o uis.o lcr_ifact.o
+- $(CC) $(LDFLAGS) test.o lcr_ifact.o uis.o -lpthread -o test
++ $(CC) $(LDFLAGS) -fPIC test.o lcr_ifact.o uis.o -lpthread -o test
+
+ test_static: test.o libtest_a.o libtest_b.o uis.o lcr_ifact.o
+ $(CC) $(LDFLAGS) test.o libtest_a.o libtest_b.o lcr_ifact.o -o test_static
+@@ -71,6 +71,12 @@
+ libtest_b.o: libtest_b.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c -o $@ $(*F).c
+
++lcr_ifact.o: lcr_ifact.c
++ $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c -o $@ $(*F).c
++
++test.o: test.c
++ $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c -o $@ $(*F).c
++
+ clean:
+ rm -f test libtest.so* *.o uic liblcr.so* liblcr.a *.lcrso *.da *.ba *.bb *.bbg \
+ test_static
+diff -uNr openais-0.80.3/lcr/lcr_ifact.c openais-0.80.3-r1661/lcr/lcr_ifact.c
+--- openais-0.80.3/lcr/lcr_ifact.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lcr/lcr_ifact.c 2008-11-17 15:53:59.910615969 +0100
+@@ -45,6 +45,7 @@
+ struct lcr_component_instance {
+ struct lcr_iface *ifaces;
+ int iface_count;
++ unsigned int comp_handle;
+ void *dl_handle;
+ int refcount;
+ char library_name[256];
+@@ -68,7 +69,7 @@
+ .iterator = 0
+ };
+
+-static unsigned int g_component_handle;
++static unsigned int g_component_handle = 0xFFFFFFFF;
+
+ #ifdef OPENAIS_LINUX
+ static int lcr_select_so (const struct dirent *dirent)
+@@ -170,7 +171,6 @@
+
+ res = getcwd (cwd, sizeof (cwd));
+ if (res != NULL) {
+- strcat (cwd, "/");
+ path_list[0] = strdup (cwd);
+ path_list_entries++;
+ }
+@@ -291,6 +291,8 @@
+ }
+ dl_handle = dlopen (dl_name, RTLD_LAZY);
+ if (dl_handle == NULL) {
++ fprintf (stderr, "LCR error loading plugin: %s\n",
++ dlerror());
+ continue;
+ }
+ instance = lcr_comp_find (iface_name, version, iface_number);
+@@ -301,8 +303,8 @@
+ }
+
+ /*
+- * No matching interfaces found, try next shared object
+- */
++ * No matching interfaces found, try next shared object
++ */
+ if (g_component_handle != 0xFFFFFFFF) {
+ hdb_handle_destroy (&lcr_component_instance_database,
+ g_component_handle);
+@@ -349,19 +351,19 @@
+
+ // TODO error checking in this code is weak
+ /*
+- * Find all *.lcrso files in search paths
++ * Search through all lcrso files for desired interface
+ */
+ for (i = 0; i < path_list_entries; i++) {
+- res = interface_find_and_load (
+- path_list[i],
+- iface_name,
+- version,
+- &instance,
+- &iface_number);
++ res = interface_find_and_load (
++ path_list[i],
++ iface_name,
++ version,
++ &instance,
++ &iface_number);
+
+- if (res == 0) {
+- goto found;
+- }
++ if (res == 0) {
++ goto found;
++ }
+ }
+
+ /*
+@@ -379,9 +381,10 @@
+ iface_handle);
+ hdb_handle_get (&lcr_iface_instance_database,
+ *iface_handle, (void *)&iface_instance);
+- iface_instance->component_handle = g_component_handle;
++ iface_instance->component_handle = instance->comp_handle;
+ iface_instance->context = context;
+ iface_instance->destructor = instance->ifaces[iface_number].destructor;
++ hdb_handle_put (&lcr_iface_instance_database, *iface_handle);
+ return (0);
+ }
+
+@@ -408,17 +411,21 @@
+ void lcr_component_register (struct lcr_comp *comp)
+ {
+ struct lcr_component_instance *instance;
++ static unsigned int comp_handle;
+
+ hdb_handle_create (&lcr_component_instance_database,
+ sizeof (struct lcr_component_instance),
+- &g_component_handle);
++ &comp_handle);
+ hdb_handle_get (&lcr_component_instance_database,
+- g_component_handle, (void *)&instance);
++ comp_handle, (void *)&instance);
+
+ instance->ifaces = comp->ifaces;
+ instance->iface_count = comp->iface_count;
++ instance->comp_handle = comp_handle;
+ instance->dl_handle = NULL;
+
+ hdb_handle_put (&lcr_component_instance_database,
+- g_component_handle);
++ comp_handle);
++
++ g_component_handle = comp_handle;
+ }
+diff -uNr openais-0.80.3/lcr/test.c openais-0.80.3-r1661/lcr/test.c
+--- openais-0.80.3/lcr/test.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lcr/test.c 2008-11-17 15:53:59.900633359 +0100
+@@ -87,7 +87,7 @@
+ (void *)0xaaaa1111);
+ assert (res == 0);
+
+- a_iface_ver1 = (struct iface *)a_iface_ver0_p;
++ a_iface_ver1 = (struct iface *)a_iface_ver1_p;
+
+ res = lcr_ifact_reference (
+ &b_ifact_handle_ver1,
+@@ -97,7 +97,7 @@
+ (void *)0xbbbb1111);
+ assert (res == 0);
+
+- b_iface_ver1 = (struct iface *)b_iface_ver0_p;
++ b_iface_ver1 = (struct iface *)b_iface_ver1_p;
+
+ a_iface_ver0->func1();
+ a_iface_ver0->func2();
+diff -uNr openais-0.80.3/lib/amf.c openais-0.80.3-r1661/lib/amf.c
+--- openais-0.80.3/lib/amf.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/amf.c 2008-11-17 15:54:03.480606331 +0100
+@@ -101,6 +101,10 @@
+
+ void amfHandleInstanceDestructor (void *instance)
+ {
++ struct amfInstance *amfInstance = instance;
++
++ pthread_mutex_destroy (&amfInstance->response_mutex);
++ pthread_mutex_destroy (&amfInstance->dispatch_mutex);
+ }
+
+ SaAisErrorT
+diff -uNr openais-0.80.3/lib/cfg.c openais-0.80.3-r1661/lib/cfg.c
+--- openais-0.80.3/lib/cfg.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/cfg.c 2008-11-17 15:54:03.480606331 +0100
+@@ -88,6 +88,10 @@
+ */
+ void cfg_handleInstanceDestructor (void *instance)
+ {
++ struct cfg_instance *cfg_instance = instance;
++
++ pthread_mutex_destroy (&cfg_instance->response_mutex);
++ pthread_mutex_destroy (&cfg_instance->dispatch_mutex);
+ }
+
+ SaAisErrorT
+diff -uNr openais-0.80.3/lib/ckpt.c openais-0.80.3-r1661/lib/ckpt.c
+--- openais-0.80.3/lib/ckpt.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/ckpt.c 2008-11-17 15:54:03.480606331 +0100
+@@ -155,15 +155,24 @@
+ */
+ void ckptHandleInstanceDestructor (void *instance)
+ {
++ struct ckptInstance *ckptInstance = instance;
++
++ pthread_mutex_destroy (&ckptInstance->response_mutex);
++ pthread_mutex_destroy (&ckptInstance->dispatch_mutex);
+ }
+
+ void checkpointHandleInstanceDestructor (void *instance)
+ {
+- return;
++ struct ckptCheckpointInstance *checkpointInstance = instance;
++
++ pthread_mutex_destroy (&checkpointInstance->response_mutex);
+ }
+
+ void ckptSectionIterationHandleInstanceDestructor (void *instance)
+ {
++ struct ckptSectionIterationInstance *iterationInstance = instance;
++
++ pthread_mutex_destroy (&iterationInstance->response_mutex);
+ }
+
+ static void ckptSectionIterationInstanceFinalize (struct ckptSectionIterationInstance *ckptSectionIterationInstance)
+@@ -191,8 +200,6 @@
+
+ saHandleDestroy (&ckptSectionIterationHandleDatabase,
+ ckptSectionIterationInstance->sectionIterationHandle);
+-
+- pthread_mutex_destroy (&ckptSectionIterationInstance->response_mutex);
+ }
+
+ static void ckptCheckpointInstanceFinalize (struct ckptCheckpointInstance *ckptCheckpointInstance)
+@@ -216,8 +223,6 @@
+ list_del (&ckptCheckpointInstance->list);
+
+ saHandleDestroy (&checkpointHandleDatabase, ckptCheckpointInstance->checkpointHandle);
+-
+- pthread_mutex_destroy (&ckptCheckpointInstance->response_mutex);
+ }
+
+ static void ckptInstanceFinalize (struct ckptInstance *ckptInstance)
+@@ -1027,7 +1032,7 @@
+ SaCkptCheckpointHandleT checkpointHandle,
+ SaCkptSectionCreationAttributesT *sectionCreationAttributes,
+ const void *initialData,
+- SaUint32T initialDataSize)
++ SaSizeT initialDataSize)
+ {
+ SaAisErrorT error;
+ struct ckptCheckpointInstance *ckptCheckpointInstance;
+diff -uNr openais-0.80.3/lib/clm.c openais-0.80.3-r1661/lib/clm.c
+--- openais-0.80.3/lib/clm.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/clm.c 2008-11-17 15:54:03.490605981 +0100
+@@ -92,6 +92,10 @@
+
+ void clmHandleInstanceDestructor (void *instance)
+ {
++ struct clmInstance *clmInstance = instance;
++
++ pthread_mutex_destroy (&clmInstance->response_mutex);
++ pthread_mutex_destroy (&clmInstance->dispatch_mutex);
+ }
+
+
+@@ -494,9 +498,6 @@
+ clmInstance->finalize = 1;
+
+ pthread_mutex_unlock (&clmInstance->response_mutex);
+- pthread_mutex_destroy (&clmInstance->response_mutex);
+-
+- pthread_mutex_destroy (&clmInstance->dispatch_mutex);
+
+ saHandleDestroy (&clmHandleDatabase, clmHandle);
+
+diff -uNr openais-0.80.3/lib/cpg.c openais-0.80.3-r1661/lib/cpg.c
+--- openais-0.80.3/lib/cpg.c 2007-06-25 05:09:31.000000000 +0200
++++ openais-0.80.3-r1661/lib/cpg.c 2008-11-17 15:54:03.490605981 +0100
+@@ -1,7 +1,7 @@
+ /*
+ * vi: set autoindent tabstop=4 shiftwidth=4 :
+ *
+- * Copyright (c) 2006-2007 Red Hat, Inc.
++ * Copyright (c) 2006-2008 Red Hat, Inc.
+ *
+ * All rights reserved.
+ *
+@@ -76,6 +76,10 @@
+ */
+ static void cpg_instance_destructor (void *instance)
+ {
++ struct cpg_inst *cpg_inst = instance;
++
++ pthread_mutex_destroy (&cpg_inst->response_mutex);
++ pthread_mutex_destroy (&cpg_inst->dispatch_mutex);
+ }
+
+
+@@ -103,8 +107,7 @@
+ goto error_destroy;
+ }
+
+- error = saServiceConnect (&cpg_inst->dispatch_fd,
+- &cpg_inst->response_fd,
++ error = saServiceConnect (&cpg_inst->response_fd, &cpg_inst->dispatch_fd,
+ CPG_SERVICE);
+ if (error != SA_AIS_OK) {
+ goto error_put_destroy;
+@@ -153,9 +156,6 @@
+ cpg_inst->finalize = 1;
+
+ pthread_mutex_unlock (&cpg_inst->response_mutex);
+- pthread_mutex_destroy (&cpg_inst->response_mutex);
+-
+- pthread_mutex_destroy (&cpg_inst->dispatch_mutex);
+
+ saHandleDestroy (&cpg_handle_t_db, handle);
+
+@@ -457,7 +457,7 @@
+ iov[0].iov_base = &req_lib_cpg_trackstart;
+ iov[0].iov_len = sizeof (struct req_lib_cpg_trackstart);
+
+- error = saSendMsgReceiveReply (cpg_inst->dispatch_fd, iov, 1,
++ error = saSendMsgReceiveReply (cpg_inst->response_fd, iov, 1,
+ &res_lib_cpg_trackstart, sizeof (struct res_lib_cpg_trackstart));
+
+ if (error != SA_AIS_OK) {
+diff -uNr openais-0.80.3/lib/evs.c openais-0.80.3-r1661/lib/evs.c
+--- openais-0.80.3/lib/evs.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/evs.c 2008-11-17 15:54:03.490605981 +0100
+@@ -80,6 +80,10 @@
+ */
+ static void evs_instance_destructor (void *instance)
+ {
++ struct evs_inst *evs_inst = instance;
++
++ pthread_mutex_destroy (&evs_inst->response_mutex);
++ pthread_mutex_destroy (&evs_inst->dispatch_mutex);
+ }
+
+
+@@ -162,9 +166,6 @@
+ evs_inst->finalize = 1;
+
+ pthread_mutex_unlock (&evs_inst->response_mutex);
+- pthread_mutex_destroy (&evs_inst->response_mutex);
+-
+- pthread_mutex_destroy (&evs_inst->dispatch_mutex);
+
+ saHandleDestroy (&evs_handle_t_db, handle);
+ /*
+diff -uNr openais-0.80.3/lib/evt.c openais-0.80.3-r1661/lib/evt.c
+--- openais-0.80.3/lib/evt.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/evt.c 2008-11-17 15:54:03.480606331 +0100
+@@ -110,10 +110,12 @@
+ * ei_version: version sent to the evtInitialize call.
+ * ei_node_id: our node id.
+ * ei_node_name: our node name.
+- * ei_finalize: instance in finalize flag
+- * ei_dispatch_mutex: mutex for dispatch fd
++ * ei_dispatch_mutex: mutex for dispatch fd. This lock also ensures that
++ * only one thread is using ei_dispatch_data.
+ * ei_response_mutex: mutex for response fd
+ * ei_channel_list: list of associated channels (struct handle_list)
++ * ei_dispatch_data: event buffer for evtDispatch
++ * ei_finalize: instance in finalize flag
+ * ei_data_available: Indicates that there is a pending event message though
+ * there may not be a poll event. This can happen
+ * when we get a SA_AIS_ERR_TRY_AGAIN when asking for an
+@@ -127,11 +129,12 @@
+ SaVersionT ei_version;
+ SaClmNodeIdT ei_node_id;
+ SaNameT ei_node_name;
+- int ei_finalize;
+ pthread_mutex_t ei_dispatch_mutex;
+ pthread_mutex_t ei_response_mutex;
+ struct list_head ei_channel_list;
+- int ei_data_available;
++ struct res_overlay ei_dispatch_data;
++ unsigned int ei_finalize:1;
++ unsigned int ei_data_available:1;
+ };
+
+
+@@ -245,6 +248,9 @@
+ saHandleDestroy(&channel_handle_db, handle);
+ saHandleInstancePut(&channel_handle_db, handle);
+ }
++
++ pthread_mutex_destroy(&evti->ei_dispatch_mutex);
++ pthread_mutex_destroy(&evti->ei_response_mutex);
+ }
+
+ /*
+@@ -272,6 +278,7 @@
+ saEvtEventFree(handle);
+ }
+
++ pthread_mutex_destroy(&eci->eci_mutex);
+ }
+
+ /*
+@@ -296,6 +303,8 @@
+ if (edi->edi_event_data) {
+ free(edi->edi_event_data);
+ }
++
++ pthread_mutex_destroy(&edi->edi_mutex);
+ }
+
+ static SaAisErrorT evt_recv_event(int fd, struct lib_event_data **msg)
+@@ -599,7 +608,6 @@
+ int ignore_dispatch = 0;
+ int cont = 1; /* always continue do loop except when set to 0 */
+ int poll_fd;
+- struct res_overlay dispatch_data;
+ struct lib_event_data *evt = 0;
+ struct res_evt_event_data res;
+
+@@ -674,15 +682,15 @@
+ }
+
+ if (ufds.revents & POLLIN) {
+- error = saRecvRetry (evti->ei_dispatch_fd, &dispatch_data.header,
++ error = saRecvRetry (evti->ei_dispatch_fd, &evti->ei_dispatch_data.header,
+ sizeof (mar_res_header_t));
+
+ if (error != SA_AIS_OK) {
+ goto dispatch_unlock;
+ }
+- if (dispatch_data.header.size > sizeof (mar_res_header_t)) {
+- error = saRecvRetry (evti->ei_dispatch_fd, &dispatch_data.data,
+- dispatch_data.header.size - sizeof (mar_res_header_t));
++ if (evti->ei_dispatch_data.header.size > sizeof (mar_res_header_t)) {
++ error = saRecvRetry (evti->ei_dispatch_fd, &evti->ei_dispatch_data.data,
++ evti->ei_dispatch_data.header.size - sizeof (mar_res_header_t));
+ if (error != SA_AIS_OK) {
+ goto dispatch_unlock;
+ }
+@@ -697,7 +705,7 @@
+ * Fake up a header message and the switch statement will
+ * take care of the rest.
+ */
+- dispatch_data.header.id = MESSAGE_RES_EVT_AVAILABLE;
++ evti->ei_dispatch_data.header.id = MESSAGE_RES_EVT_AVAILABLE;
+ }
+
+ /*
+@@ -707,13 +715,11 @@
+ * EvtFinalize has been called in another thread.
+ */
+ memcpy(&callbacks, &evti->ei_callback, sizeof(evti->ei_callback));
+- pthread_mutex_unlock(&evti->ei_dispatch_mutex);
+-
+
+ /*
+ * Dispatch incoming response
+ */
+- switch (dispatch_data.header.id) {
++ switch (evti->ei_dispatch_data.header.id) {
+
+ case MESSAGE_RES_EVT_AVAILABLE:
+ evti->ei_data_available = 0;
+@@ -782,7 +788,7 @@
+ case MESSAGE_RES_EVT_CHAN_OPEN_CALLBACK:
+ {
+ struct res_evt_open_chan_async *resa =
+- (struct res_evt_open_chan_async *)&dispatch_data;
++ (struct res_evt_open_chan_async *)&evti->ei_dispatch_data;
+ struct event_channel_instance *eci;
+
+ /*
+@@ -815,11 +821,13 @@
+ break;
+
+ default:
+- DPRINT (("Dispatch: Bad message type 0x%x\n", dispatch_data.header.id));
++ DPRINT (("Dispatch: Bad message type 0x%x\n", evti->ei_dispatch_data.header.id));
+ error = SA_AIS_ERR_LIBRARY;
+- goto dispatch_put;
++ goto dispatch_unlock;
+ }
+
++ pthread_mutex_unlock(&evti->ei_dispatch_mutex);
++
+ /*
+ * If empty is zero it means the we got the
+ * message from the queue and we are responsible
+@@ -854,7 +862,7 @@
+ goto dispatch_put;
+
+ dispatch_unlock:
+- pthread_mutex_unlock(&evti->ei_dispatch_mutex);
++ pthread_mutex_unlock(&evti->ei_dispatch_mutex);
+ dispatch_put:
+ saHandleInstancePut(&evt_instance_handle_db, evtHandle);
+ return error;
+@@ -896,9 +904,6 @@
+ evti->ei_finalize = 1;
+
+ pthread_mutex_unlock (&evti->ei_response_mutex);
+- pthread_mutex_destroy (&evti->ei_response_mutex);
+-
+- pthread_mutex_destroy (&evti->ei_dispatch_mutex);
+
+ saHandleDestroy(&evt_instance_handle_db, evtHandle);
+ /*
+diff -uNr openais-0.80.3/lib/lck.c openais-0.80.3-r1661/lib/lck.c
+--- openais-0.80.3/lib/lck.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/lck.c 2008-11-17 15:54:03.480606331 +0100
+@@ -144,11 +144,14 @@
+ */
+ void lckHandleInstanceDestructor (void *instance)
+ {
++ struct lckInstance *lckInstance = instance;
++
++ pthread_mutex_destroy (&lckInstance->response_mutex);
++ pthread_mutex_destroy (&lckInstance->dispatch_mutex);
+ }
+
+ void lckResourceHandleInstanceDestructor (void *instance)
+ {
+- return;
+ }
+
+ void lckResourceHandleLockIdInstanceDestructor (void *instance)
+diff -uNr openais-0.80.3/lib/msg.c openais-0.80.3-r1661/lib/msg.c
+--- openais-0.80.3/lib/msg.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/msg.c 2008-11-17 15:54:03.490605981 +0100
+@@ -131,11 +131,14 @@
+ */
+ void msgHandleInstanceDestructor (void *instance)
+ {
++ struct msgInstance *msgInstance = instance;
++
++ pthread_mutex_destroy (&msgInstance->response_mutex);
++ pthread_mutex_destroy (&msgInstance->dispatch_mutex);
+ }
+
+ void queueHandleInstanceDestructor (void *instance)
+ {
+- return;
+ }
+
+ #ifdef COMPILE_OUT
+diff -uNr openais-0.80.3/lib/util.c openais-0.80.3-r1661/lib/util.c
+--- openais-0.80.3/lib/util.c 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/lib/util.c 2008-11-17 15:54:03.490605981 +0100
+@@ -543,7 +543,7 @@
+ handleDatabase->handleCount += 1;
+ newHandles = (struct saHandle *)realloc (handleDatabase->handles,
+ sizeof (struct saHandle) * handleDatabase->handleCount);
+- if (newHandles == 0) {
++ if (newHandles == NULL) {
+ pthread_mutex_unlock (&handleDatabase->mutex);
+ return (SA_AIS_ERR_NO_MEMORY);
+ }
+@@ -552,6 +552,8 @@
+
+ instance = malloc (instanceSize);
+ if (instance == 0) {
++ free (newHandles);
++ pthread_mutex_unlock (&handleDatabase->mutex);
+ return (SA_AIS_ERR_NO_MEMORY);
+ }
+
+diff -uNr openais-0.80.3/man/openais.conf.5 openais-0.80.3-r1661/man/openais.conf.5
+--- openais-0.80.3/man/openais.conf.5 2007-06-24 08:33:09.000000000 +0200
++++ openais-0.80.3-r1661/man/openais.conf.5 2008-11-17 15:54:04.010616877 +0100
+@@ -135,6 +135,17 @@
+ reserved and should not be used.
+
+ .TP
++clear_node_high_bit
++This configuration option is optional and is only relevant when no nodeid is
++specified. Some openais clients require a signed 32 bit nodeid that is greater
++than zero however by default openais uses all 32 bits of the IPv4 address space
++when generating a nodeid. Set this option to yes to force the high bit to be
++zero and therefor ensure the nodeid is a positive signed 32 bit integer.
++
++WARNING: The clusters behavior is undefined if this option is enabled on only
++a subset of the cluster (for example during a rolling upgrade).
++
++.TP
+ secauth
+ This specifies that HMAC/SHA1 authentication should be used to authenticate
+ all messages. It further specifies that all data should be encrypted with the
+diff -uNr openais-0.80.3/test/Makefile openais-0.80.3-r1661/test/Makefile
+--- openais-0.80.3/test/Makefile 2007-06-25 04:52:58.000000000 +0200
++++ openais-0.80.3-r1661/test/Makefile 2008-11-17 15:53:59.760604514 +0100
+@@ -49,7 +49,7 @@
+
+ all: testclm testamf1 \
+ testckpt ckptstress ckptbench \
+- ckptbenchth ckpt-rd ckpt-wr testevt testevs \
++ ckptbenchth ckpt-rd ckpt-wr ckpt-overload-exit testevt testevs \
+ evsbench subscription publish evtbench unlink testclm2 testlck \
+ testmsg testcpg testcpg2 cpgbench openais-cfgtool
+
+@@ -128,6 +128,9 @@
+ ckpt-wr: ckpt-wr.o sa_error.o $(LIBRARIES)
+ $(CC) $(LDFLAGS) -o ckpt-wr ckpt-wr.o sa_error.o $(LIBS)
+
++ckpt-overload-exit: ckpt-overload-exit.o sa_error.o $(LIBRARIES)
++ $(CC) $(LDFLAGS) -o ckpt-overload-exit ckpt-overload-exit.o sa_error.o $(LIBS)
++
+ testclm2: testclm2.o $(LIBRARIES)
+ $(CC) $(LDFLAGS) -o testclm2 testclm2.o $(LIBS)
+
+diff -uNr openais-0.80.3/test/ckpt-overload-exit.c openais-0.80.3-r1661/test/ckpt-overload-exit.c
+--- openais-0.80.3/test/ckpt-overload-exit.c 1970-01-01 01:00:00.000000000 +0100
++++ openais-0.80.3-r1661/test/ckpt-overload-exit.c 2008-11-17 15:53:59.760604514 +0100
+@@ -0,0 +1,157 @@
++/*
++ * Copyright (c) 2008 Red Hat, Inc.
++ *
++ * All rights reserved.
++ *
++ * Author: Steven Dake (sdake@redhat.com)
++ *
++ * This software licensed under BSD license, the text of which follows:
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are met:
++ *
++ * - Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ * - Redistributions in binary form must reproduce the above copyright notice,
++ * this list of conditions and the following disclaimer in the documentation
++ * and/or other materials provided with the distribution.
++ * - Neither the name of the MontaVista Software, Inc. nor the names of its
++ * contributors may be used to endorse or promote products derived from this
++ * software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
++ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
++ * THE POSSIBILITY OF SUCH DAMAGE.
++ */
++/*
++ * Overloads the ckpt system with checkpoints (30k checkpoints) and then exits
++ * ungracefully. This will cause the entire system to go into overload
++ * as it sends out close messages for the 30k open checkpoints.
++ */
++
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/select.h>
++#include <sys/un.h>
++#include <time.h>
++
++#include "saAis.h"
++#include "saCkpt.h"
++#include "sa_error.h"
++
++#define SECONDS_TO_EXPIRE 500
++
++int ckptinv;
++void printSaNameT (SaNameT *name)
++{
++ int i;
++
++ for (i = 0; i < name->length; i++) {
++ printf ("%c", name->value[i]);
++ }
++}
++
++SaVersionT version = { 'B', 1, 1 };
++
++SaNameT checkpointName = { 16, "checkpoint-sync\0" };
++
++SaCkptCheckpointCreationAttributesT checkpointCreationAttributes = {
++ .creationFlags = SA_CKPT_WR_ALL_REPLICAS,
++ .checkpointSize = 250000,
++ .retentionDuration = SA_TIME_ONE_SECOND * 60,
++ .maxSections = 1,
++ .maxSectionSize = 250000,
++ .maxSectionIdSize = 10
++};
++
++char readBuffer1[1025];
++
++SaCkptIOVectorElementT ReadVectorElements[] = {
++ {
++ SA_CKPT_DEFAULT_SECTION_ID,
++ readBuffer1,
++ sizeof (readBuffer1),
++ 0,
++ 0
++ }
++};
++
++#define DATASIZE 127000
++char data[DATASIZE];
++SaCkptIOVectorElementT WriteVectorElements[] = {
++ {
++ SA_CKPT_DEFAULT_SECTION_ID,
++ data, /*"written data #1, this should extend past end of old section data", */
++ DATASIZE, /*sizeof ("data #1, this should extend past end of old section data") + 1, */
++ 0, //5,
++ 0
++ }
++};
++
++SaCkptCallbacksT callbacks = {
++ 0,
++ 0
++};
++
++#define MAX_DATA_SIZE 100
++
++int main (void) {
++ SaCkptHandleT ckptHandle;
++ SaCkptCheckpointHandleT checkpointHandle;
++ SaAisErrorT error;
++ char data[MAX_DATA_SIZE];
++ SaCkptIOVectorElementT writeElement;
++ SaUint32T erroroneousVectorIndex = 0;
++ int i;
++
++ error = saCkptInitialize (&ckptHandle, &callbacks, &version);
++ printf ("%s: CkptInitialize\n",
++ get_test_output (error, SA_AIS_OK));
++
++ for (i = 0; i < 30000; i++) {
++ checkpointName.length =
++ sprintf((char*)checkpointName.value, "ckp%05d",i);
++
++ do {
++ error = saCkptCheckpointOpen (ckptHandle,
++ &checkpointName,
++ &checkpointCreationAttributes,
++ SA_CKPT_CHECKPOINT_CREATE|SA_CKPT_CHECKPOINT_READ|SA_CKPT_CHECKPOINT_WRITE,
++ 0,
++ &checkpointHandle);
++ } while (error == SA_AIS_ERR_TRY_AGAIN);
++
++ sprintf((char*)&data, "%04d", i);
++ writeElement.sectionId = (SaCkptSectionIdT)SA_CKPT_DEFAULT_SECTION_ID;
++ writeElement.dataBuffer = data;
++ writeElement.dataSize = strlen (data) + 1;
++ writeElement.dataOffset = 0;
++ writeElement.readSize = 0;
++
++ do {
++ error = saCkptCheckpointWrite (checkpointHandle,
++ &writeElement,
++ 1,
++ &erroroneousVectorIndex);
++
++ } while (error == SA_AIS_ERR_TRY_AGAIN);
++
++ }
++
++ return (0);
++
++}
+diff -uNr openais-0.80.3/test/testckpt.c openais-0.80.3-r1661/test/testckpt.c
+--- openais-0.80.3/test/testckpt.c 2007-06-25 10:42:58.000000000 +0200
++++ openais-0.80.3-r1661/test/testckpt.c 2008-11-17 15:53:59.760604514 +0100
+@@ -341,7 +341,7 @@
+ timersub (&tv_end, &tv_start, &tv_elapsed);
+ printf ("Elapsed Time to expiry is %ld & %ld usec (should be about %d seconds)\n",
+ tv_elapsed.tv_sec,
+- tv_elapsed.tv_usec,
++ (long) tv_elapsed.tv_usec,
+ SECONDS_TO_EXPIRE);
+
+ error = saCkptCheckpointRetentionDurationSet (checkpointHandle,
diff --git a/sys-cluster/openais/openais-0.80.3.ebuild b/sys-cluster/openais/openais-0.80.3-r1.ebuild
index 9a044328a86f..84ed541aed59 100644
--- a/sys-cluster/openais/openais-0.80.3.ebuild
+++ b/sys-cluster/openais/openais-0.80.3-r1.ebuild
@@ -1,6 +1,6 @@
# Copyright 1999-2008 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/sys-cluster/openais/openais-0.80.3.ebuild,v 1.1 2008/03/17 16:02:41 xmerlin Exp $
+# $Header: /var/cvsroot/gentoo-x86/sys-cluster/openais/openais-0.80.3-r1.ebuild,v 1.1 2008/11/21 22:55:48 xmerlin Exp $
inherit eutils flag-o-matic toolchain-funcs
@@ -20,6 +20,16 @@ src_unpack() {
epatch "${FILESDIR}"/${P}-Makefile-ARCH.patch || die
epatch "${FILESDIR}"/${P}-Makefile-LIBDIR.patch || die
epatch "${FILESDIR}"/${P}-Makefile.inc-FLAGS.patch || die
+
+ epatch "${FILESDIR}"/${P}-Makefile.inc-VARS.patch || die
+ epatch "${FILESDIR}"/${P}-Makefile-VARS.patch || die
+
+ #epatch "${FILESDIR}"/${P}-r1514.patch || die
+ epatch "${FILESDIR}"/${P}-r1661.patch || die
+
+ #epatch "${FILESDIR}"/${P}-r1661-pacemaker-openais.conf.patch || die
+ #epatch "${FILESDIR}"/${P}-r1661-pacemaker.patch || die
+ #epatch "${FILESDIR}"/pacemaker.diff || die
}
pkg_setup() {