Page MenuHomeClusterLabs Projects

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Doxyfile b/Doxyfile
index ee53bae1..d9e25ceb 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,164 +1,164 @@
# Doxyfile 0.1
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = corosync
PROJECT_NUMBER = 0.75
OUTPUT_DIRECTORY = doc/api
OUTPUT_LANGUAGE = English
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
FULL_PATH_NAMES = NO
-STRIP_FROM_PATH =
+STRIP_FROM_PATH =
INTERNAL_DOCS = NO
STRIP_CODE_COMMENTS = YES
CASE_SENSE_NAMES = YES
SHORT_NAMES = NO
HIDE_SCOPE_NAMES = NO
VERBATIM_HEADERS = YES
SHOW_INCLUDE_FILES = YES
JAVADOC_AUTOBRIEF = YES
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
-ALIASES =
-ENABLED_SECTIONS =
+ALIASES =
+ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = YES
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
-WARN_FORMAT =
-WARN_LOGFILE =
+WARN_FORMAT =
+WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = lib include exec
FILE_PATTERNS = *.c *.h
RECURSIVE = YES
-EXAMPLE_PATH =
-EXAMPLE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
-IMAGE_PATH =
-INPUT_FILTER =
+IMAGE_PATH =
+INPUT_FILTER =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
-IGNORE_PREFIX =
+IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
-HTML_OUTPUT =
-HTML_HEADER =
-HTML_FOOTER =
-HTML_STYLESHEET =
+HTML_OUTPUT =
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
-LATEX_OUTPUT =
+LATEX_OUTPUT =
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
-EXTRA_PACKAGES =
-LATEX_HEADER =
+EXTRA_PACKAGES =
+LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
-RTF_OUTPUT =
+RTF_OUTPUT =
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
-RTF_STYLESHEET_FILE =
-RTF_EXTENSIONS_FILE =
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = YES
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
+# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = include
INCLUDE_FILE_PATTERNS = *.h
PREDEFINED = "COROSYNC_BEGIN_DECLS=" \
"COROSYNC_END_DECLS=" \
- "DOXYGEN_SHOULD_SKIP_THIS"
+ "DOXYGEN_SHOULD_SKIP_THIS"
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to external references
+# Configuration::addtions related to external references
#---------------------------------------------------------------------------
-TAGFILES =
-GENERATE_TAGFILE =
+TAGFILES =
+GENERATE_TAGFILE =
ALLEXTERNALS = NO
-PERL_PATH =
+PERL_PATH =
#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
+# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
TEMPLATE_RELATIONS = YES
HIDE_UNDOC_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
GRAPHICAL_HIERARCHY = YES
-DOT_PATH =
-DOTFILE_DIRS =
+DOT_PATH =
+DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 640
MAX_DOT_GRAPH_HEIGHT = 1024
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
-# Configuration::addtions related to the search engine
+# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
diff --git a/LICENSE b/LICENSE
index e30734f4..e0a0680f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,61 +1,61 @@
***
All cryptographic software in this package is subject to the following legal
notice:
This package includes publicly available encryption source code which,
together with object code resulting from the compiling of publicly
available source code, may be exported from the United States under License
Exception TSU prsuant to 15 C.F.R Section 740.13(e).
***
-----------------------------------------------------------------------------
-The following license applies to every file in this package except for
+The following license applies to every file in this package except for
the files exec/crypto.c and exec/crypto.h. The license for these files is
described later in this document. Some files are contributed by other authors
and hence not copyright MontaVista Software. In this case, the license is
still as follows:
-----------------------------------------------------------------------------
Copyright (c) 2002-2004 MontaVista Software, Inc.
All rights reserved.
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.
-----------------------------------------------------------------------------
The corosync project uses software from the LibTomCrypt project
www.libtomcrypt.org. This software is contained the files exec/crypto.c and
exec/crypto.h. The following license applies to the files exec/crypto.c and
exec/crytpo.h:
-----------------------------------------------------------------------------
LibTomCrypt is public domain. As should all quality software be.
All of the software was either written by or donated to Tom St Denis for the
purposes of this project. The only exception is the SAFER.C source which has
no known license status (assumed copyrighted) which is why SAFER,C is shipped
as disabled.
Tom St Denis
diff --git a/Makefile.am b/Makefile.am
index bb205196..5c93d2a0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,57 +1,57 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
EXTRA_DIST = autogen.sh conf/corosync.conf.example
AUTOMAKE_OPTIONS = foreign
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \
config.guess config.sub missing install-sh \
autoheader automake autoconf
dist_doc_DATA = LICENSE INSTALL README.devmap \
README.recovery SECURITY TODO AUTHORS
sysconf_DATA = conf/corosync.conf.example
SUBDIRS = include lcr lib exec services tools test pkgconfig man
# init
lint:
for dir in lcr lib exec services tools test; do make -C $$dir lint; done
doxygen:
mkdir -p doc/api && doxygen
dist-clean-local:
rm -f autoconf automake autoheader $(TARFILE)
clean-generic:
rm -rf doc/api
diff --git a/README.devmap b/README.devmap
index 32fd4d97..2300c38d 100644
--- a/README.devmap
+++ b/README.devmap
@@ -1,1223 +1,1223 @@
Copyright (c) 2002-2004 MontaVista Software, Inc.
Copyright (c) 2006, 2009 Red Hat, Inc.
All rights reserved.
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.
-------------------------------------------------------------------------------
This file provides a map for developers to understand how to contribute
to the corosync project. The purpose of this document is to prepare a
developer to write a service for corosync, or understand the architecture
of corosync.
The following is described in this document:
* all files, purpose, and dependencies
* architecture of corosync
* taking advantage of virtual synchrony
* adding libraries
* adding services
-------------------------------------------------------------------------------
all files, purpose, and dependencies.
-------------------------------------------------------------------------------
*----------------*
*- AIS INCLUDES -*
*----------------*
include/saAmf.h
-----------------
Definitions for AMF interface.
include/saCkpt.h
------------------
Definitions for CKPT interface.
include/saClm.h
-----------------
Definitions for CLM interface.
include/saAmf.h
-----------------
Definitions for the AMF interface.
include/saEvt.h
-----------------
Defintiions for the EVT interface.
include/saLck.h
-----------------
Definitions for the LCK interface.
include/cfg.h
Definitions for the CFG interface.
include/cpg.h
Definitions for the CPG interface.
include/evs.h
Definitions for the EVS interface.
include/ipc_amf.h
IPC interface between client and server for AMF service.
include/ipc_cfg.h
IPC interface between client and server for CFG service.
include/ipc_ckpt.h
IPC interface between client and server for CKPT service.
include/ipc_clm.h
IPC interface between client and server for CLM service.
include/ipc_cpg.h
IPC interface between client and server for CPG service.
include/ipc_evs.h
IPC interface between client and server for EVS service.
include/ipc_evt.h
IPC interface between client and server for EVT service.
include/ipc_gen.h
IPC interface for generic operations.
include/ipc_lck.h
IPC interface between client and server for LCK service.
include/ipc_msg.h
IPC interface between client and server for MSG service.
include/hdb.h
Handle database implementation.
include/list.h
Linked list implementation.
include/swab.h
Byte swapping implementation.
include/queue.h
FIFO queue implementation.
include/sq.h
Sort queue where items are sorted according to a sequence number. Avoids
Sort, hence, install of a new element takes is O(1). Inline implementation.
depends on list.
*---------------*
* AIS LIBRARIES *
*---------------*
lib/amf.c
---------
AMF user library linked into user application.
lib/cfg.c
---------
CFG user library linked into user application.
lib/ckpt.c
---------
CKPT user library linked into user application.
lib/clm.c
---------
CLM user library linked into user application.
lib/cpg.c
---------
CPG user library linked into user application.
lib/evs.c
---------
EVS user library linked into user application.
lib/evt.c
---------
EVT user library linked into user application.
lib/lck.c
---------
LCK user library linked into user application.
lib/msg.c
---------
MSG user library linked into uer application.
lib/amf.c
---------
AMF user library linked into user application.
lib/ckpt.c
----------
CKPT user library linked into user application.
lib/evt.c
----------
EVT user library linked into user application.
lib/util.c
----------
Utility functions used by all libraries.
*-----------------*
*- AIS EXECUTIVE -*
*-----------------*
exec/aisparser.{h|c}
Parser plugin for default configuration file format.
exec/aispoll.{h|c}
Poll abstraction interface.
exec/amfapp.c
AMF application handling.
exec/amfcluster.c
AMF cluster handling.
exec/amfcomp.c
AMF component level handling.
exec/amf.h
Defines all AMF symbol names.
exec/amfnode.c
AMF node level handling.
exec/amfsg.c
AMF service group handling.
exec/amfsi.c
AMF Service instance handling.
exec/amfsu.c
AMF service unit handling.
exec/amfutil.c
AMF utility functions.
exec/cfg.c
Server side implementation of CFG service which is used to display
redundant ring status and reenabling redundant rings.
exec/ckpt.c
Server side implementation of Checkpointing (CKPT API).
exec/clm.c
Server side implementation of Cluster Membership (CLM API).
exec/cpg.c
Server side implementation of closed procss groups (CPG API).
exec/crypto.{c|h}
Cryptography functions used by corosync.
exec/evs.c
Server side implementation of extended virtual synchrony passthrough
(EVS API).
exec/evt.c
Server side implementation of Event Service (EVT API).
exec/ipc.{c|h}
All IPC operations used by corosync.
exec/jhash.h
A hash routine.
exec/keygen.c
Secret key generator used by corosync encryption tools.
exec/lck.c
Server side implementation of the distributed lock service (LCK API).
exec/main.{c|h}
Main function which connects all components together.
exec/mainconfig.{c|h}
Reads main configuration that is set in the configuration parser.
exec/mempool.{c|h}
Currently unused.
exec/msg.c
Server side implementation of message service (MSG API).
exec/objdb.{c|h}
Object database used to configure services.
exec/corosync-instantiate.c
instantiates a component by forking and exec'ing it and writing its
pid to a pid file.
exec/print.{c|h}
Non-blocking thread-based logging service with overflow protection.
exec/service.{c|h}
Service handling routines including the default service handler
description.
exec/sync.{c|h}
The synchronization service implementation.
exec/timer.{c|h}
Threaded based timer service.
exec/tlist.h
Timer list used to expire timers.
exec/totemconfig.{c.h}
The totem configuration configurator from data parsed with aisparser
in the configuration file.
exec/totem.h
General definitions for the totem protocol used by the totem stack.
exec/totemip.{c.h}
IP handling functions for totem - lowest on stack.
exec/{totemrrp.{c.h}
The totem multi ring protocool and currently unimplemented. Between
totemsrp and totempg.
exec/totemnet.{c.h}
Network handling functions for totem - between totemip and totemrrp.
exec/totempg.{c|h}
Process groups interface which is used by all applications - highest on
stack.
exec/totemrrp.{c.h}
Redundant ring functions for totem - between totemnet and totemsrp.
exec/util.{c|h}
Utility functions used by corosync executive.
exec/version.h
Defines build version.
exec/vsf.h
Virtual Synchrony plugin API.
exec/vsf_ykd.c
Virtual Synchrony YKD Dynamic Linear Voting algorithm.
exec/wthread.{c|h}
Worker threads API.
loc
---
Counts the lines of code in the AIS implementation.
-------------------------------------------------------------------------------
architecture of corosync
-------------------------------------------------------------------------------
The corosync standards based cluster framework is a generic cluster plugin
architecture used to create cluster APIs and services. Usually there are
libraries which implement APIs and are linked into the end user application.
The libraries request services from the aisexec process, called the AIS
executive. The AIS executive uses the Totem protocol stack to communicate
within the cluster and execute operations on behalf of the user. Finally the
response of the API is delivered once the operation has completed.
--------------------------------------------------
| AMF and more services libraries |
--------------------------------------------------
| IPC API |
--------------------------------------------------
| corosync Executive |
| |
| +---------+ +--------+ +---------+ |
| | Object | | AIS | | Service | |
| | Datbase | | Config | | Handler | |
| | Service | | Parser | | Manager | |
| +---------+ +--------+ +---------+ |
| +-------+ +-------+ |
| | AMF | | more | |
| |Service| |svcs...| |
| +-------+ +-------+ |
| +---------+ |
| | Sync | |
| | Service | |
| +---------+ |
| +---------+ |
| | VSF | |
| | Service | |
| +---------+ |
| +--------------------------------+ +--------+ |
| | Totem | | Timers | |
| | Stack | | API | |
| +--------------------------------+ +--------+ |
| +-----------+ |
| | Poll | |
| | Interface | |
| +-----------+ |
| |
-------------------------------------------------
Figure 1: corosync Architecture
Every application that intends to use corosync links with the libais library.
This library uses IPC, or more specifically BSD unix sockets, to communicate
with the executive. The library is a small program responsible only for
packaging the request into a message. This message is sent, using IPC, to
the executive which then processes it. The library then waits for a response.
The library itself contains very little intelligence. Some utility services
are provided:
* create a connection to the executive
* send messages to the executive
* retrieve messages from the executive
* Poll on a fd
* create a handle instance
* destroy a handle instance
* get a reference to a handle instance
* release a reference to a handle instance
-When a library connects, it sends via a message, the service type. The
+When a library connects, it sends via a message, the service type. The
service type is stored and used later to reference the message handlers
for both the library message handlers and executive message handlers.
Every message sent contains an integer identifier, which is used to index
into an array of message handlers to determine the correct message handler
to execute For the library. Hence a message is uniquely identified by the
message handler ID number and the service handler ID number.
When a library sends a message via IPC, the delivery of the message occurs
to the proper library message handler. The library message handler is
responsible for sending the message via the totem process groups API to all
nodes in the system.
This simplifies the library handler significantly. The main purpose of the
library handler should be to package the library request into a message that
can be sent to all nodes.
The totem process groups API sends the message according to the extended
virtual synchrony model. The group messaging interface also delivers the
message according to the extended virtual synchrony model. This has several
advantages which are described in the virtual synchrony section. One
advantage that must be described now is that messages are self-delivered;
-if a node sends a message, that same message is delivered back to that
+if a node sends a message, that same message is delivered back to that
node.
When the executive message is delivered, it is processed by the executive
message handler. The executive message handler contains the brains of
AIS and is responsible for making all decisions relating to the request
from the libais library user.
-------------------------------------------------------------------------------
taking advantage of virtual synchrony
-------------------------------------------------------------------------------
definitions:
processor: a system responsible for executing the virtual synchrony model
configuration: the list of processors under which messages are delivered
partition: one or more processors leave the configuration
merge: one or more processors join the configuration
group messaging: sending a message from one sender to many receivers
Virtual synchrony is a model for group messaging. This is often confused
with particular implementations of virtual synchrony. Try to focus on
what virtual syncrhony provides, not how it provides it, unless interested
in working on the group messaging interface of corosync.
Virtual synchrony provides several advantages:
* integrated membership
* strong membership guarantees
* agreed ordering of delivered messages
* same delivery of configuration changes and messages on every node
* self-delivery
* reliable communication in the face of unreliable networks
* recovery of messages sent within a configuration where possible
* use of network multicast using standard UDP/IP
Integrated membership allows the group messaging interface to give
configuration change events to the API services. This is obviously beneficial
to the cluster membership service (and its respective API0, but is helpful
to other services as described later.
Strong membership guarantees allow a distributed application to make decisions
based upon the configuration (membership). Every service in corosync registers
a configuration change function. This function is called whenever a
configuration change occurs. The information passed is the current processors,
the processors that have left the configuration, and the processors that have
joined the configuration. This information is then used to make decisions
within a distributed state machine. One example usage is that an AMF component
running a specific processor has left the configuration, so failover actions
must now be taken with the new configuration (and known components).
Virtual synchrony requires that messages may be delivered in agreed order.
FIFO order indicates that one sender and one receiver agree on the order of
messages sent. Agreed ordering takes this requirement to groups, requiring that
one sender and all receivers agree on the order of messages sent.
Consider a lock service. The service is responsible for arbitrating locks
between multiple processors in the system. With fifo ordering, this is very
difficult because a request at about the same time for a lock from two seperate
processors may arrive at all the receivers in different order. Agreed ordering
ensures that all the processors are delivered the message in the same order.
In this case the first lock message will always be from processor X, while the
second lock message will always be from processor Y. Hence the first request
is always honored by all processors, and the second request is rejected (since
the lock is taken). This is how race conditions are avoided in distributed
systems.
Every processor is delivered a configuration change and messages within a
configuration in the same order. This ensures that any distributed state
machine will make the same decisions on every processor within the
configuration. This also allows the configuration and the messages to be
considered when making decisions.
Virtual synchrony requires that every node is delivered messages that it
sends. This enables the logic to be placed in one location (the handler
for the delivery of the group message) instead of two seperate places. This
also allows messages that are sent to be ordered in the stream of other
messages within the configuration.
Certain guarantees are required by virtual synchrony. If a message is sent,
it must be delivered by every processor unless that processor fails. If a
particular processor fails, a configuration change occurs creating a new
configuration under which a new set of decisions may be made. This implies
-that even unreliable networks must reliably deliver messages. The
+that even unreliable networks must reliably deliver messages. The
mplementation in corosync works on unreliable as well as reliable networks.
Every message sent must be delivered, unless a configuration change occurs.
In the case of a configuration change, every message that can be recovered
must be recovered before the new configuration is installed. Some systems
during partition won't continue to recover messages within the old
configuration even though those messages can be recovered. Virtual synchrony
makes that impossible, except for those members that are no longer part
of a configuration.
Finally virtual syncrhony takes advantage of hardware multicast to avoid
duplicated packets and scale to large transmit rates. On 100mbit network,
corosync can approach wire speeds depending on the number of messages queued
for a particular processor.
What does all of this mean for the developer?
* messages are delivered reliably
* messages are delivered in the same order to all nodes
* configuration and messages can both be used to make decisions
-------------------------------------------------------------------------------
adding libraries
-------------------------------------------------------------------------------
The first stage in adding a library to the system is to develop the library.
Library code should follow these guidelines:
* use SA Forum coding style for SA Forum APIs to aid in debugging
* use corosync coding guidelines for APIs that are not SA Forum that
are to be merged into the corosync tree.
* implement all library code within one file named after the api.
examples are ckpt.c, clm.c, amf.c.
* use parallel structure as much as possible between different APIs
* make use of utility services provided by util.c.
* if something is needed that is generic and useful by all services,
submit patches for other libraries to use these services.
* use the reference counting handle manager for handle management.
------------------
Version checking
------------------
struct saVersionDatabase {
int versionCount;
SaVersionT *versionsSupported;
};
The versionCount number describes how many entries are in the version database.
The versionsSupported member is an array of SaVersionT describing the acceptable
versions this API supports.
An api developer specifies versions supported by adding the following C
code to the library file:
/*
* Versions supported
*/
static SaVersionT clmVersionsSupported[] = {
{ 'B', 1, 1 },
{ 'b', 1, 1 }
};
static struct saVersionDatabase clmVersionDatabase = {
sizeof (clmVersionsSupported) / sizeof (SaVersionT),
clmVersionsSupported
};
After this is specified, the following API is used to check versions:
SaErrorT
saVersionVerify (
struct saVersionDatabase *versionDatabase,
const SaVersionT *version);
An example usage of this is
SaErrorT error;
error = saVersioNVerify (&clmVersionDatabase, version);
where version is a pointer to an SaVersionT passed into the API.
error will return SA_OK if the version is valid as specified in the
version database.
------------------
Handle Instances
------------------
Every handle instance is stored in a handle database. The handle database
stores instance information for every handle used by libraries. The system
includes reference counting and is safe for use in threaded applications.
The handle database structure is:
struct saHandleDatabase {
unsigned int handleCount;
struct saHandle *handles;
pthread_mutex_t mutex;
void (*handleInstanceDestructor) (void *);
};
handleCount is the number of handles
handles is an array of handles
mutex is a pthread mutex used to mutually exclude access to the handle db
handleInstanceDestructor is a callback that is called when the handle
should be freed because its reference count as dropped to zero.
The handle database is defined in a library as follows:
static void clmHandleInstanceDestructor (void *);
static struct saHandleDatabase clmHandleDatabase = {
.handleCount = 0,
.handles = 0,
.mutex = PTHREAD_MUTEX_INITIALIZER,
.handleInstanceDestructor = clmHandleInstanceDestructor
};
There are several APIs to access the handle database:
SaErrorT
saHandleCreate (
struct saHandleDatabase *handleDatabase,
int instanceSize,
int *handleOut);
Creates an instance of size instanceSize in the handleDatabase paraemter
returning the handle number in handleOut. The handle instance reference
count starts at the value 1.
SaErrorT
saHandleDestroy (
struct saHandleDatabase *handleDatabase,
unsigned int handle);
Destroys further access to the handle. Once the handle reference count
drops to zero, the database destructor is called for the handle. The handle
instance reference count is decremented by 1.
SaErrorT
saHandleInstanceGet (
struct saHandleDatabase *handleDatabase,
unsigned int handle,
void **instance);
Gets an instance specified handle from the handleDatabase and returns
it in the instance member. If the handle is valid SA_OK is returned
otherwise an error is returned. This is used to ensure a handle is
valid. Eveyr get call increases the reference count on a handle instance
by one.
SaErrorT
saHandleInstancePut (
struct saHandleDatabase *handleDatabase,
unsigned int handle);
Decrements the reference count by 1. If the reference count indicates
the handle has been destroyed, it will then be removed from the database
and the destructor called on the instance data. The put call takes care
of freeing the handle instance data.
Create a data structure for the instance, and use it within the libraries
to store state information about the instance. This information can be
the handle, a mutex for protecting I/O, a queue for queueing async messages
or whatever is needed by the API.
-----------------------------------
communicating with the executive
-----------------------------------
A service connection is created with the following API;
SaErrorT
saServiceConnect (
int *responseOut,
int *callbackOut,
enum service_types service);
The responseOut parameter specifies the file descriptor where response messages
will be delivered. The callback out parameter describes the file descriptor
where callback messages are delivered.
The service specifies the service to use.
Messages are sent and received from the executive with the following functions:
SaAisErrorT saSendMsgRetry (
int s,
struct iovec *iov,
unsigned int iov_len);
the s member is the socket to use retrieved with saServiceConnect
The iov is the iovector used to send a message.
the iov_len is the number of elements in iov.
This sends an IO-vectorized message.
SaErrorT
saSendRetry (
int s,
const void *msg,
size_t len,
int flags);
the s member is the socket to use retrieved with saServiceConnect
the msg member is a pointer to the message to send to the service
the len member is the length of the message to send
the flags parameter is the flags to use with the sendmsg system call
This sends a data blob to the exective.
A message is received from the executive with the function:
SaErrorT
saRecvRetry (
int s,
void *msg,
size_t len,
int flags);
the s member is the socket to use retrieved with saServiceConnect
the msg member is a pointer to the message to receive to the service
the len member is the length of the message to receive
the flags parameter is the flags to use with the sendmsg system call
A message may be send and a reply waited for with the following function:
SaAisErrorT saSendMsgReceiveReply (
int s,
struct iovec *iov,
unsigned int iov_len,
void *responseMessage,
int responseLen)
s is the socket to send and receive the response.
iov is the iovector to send.
iov_len is the number of elements in iov.
responseMessage is the data block used to store the response.
responesLen is the length of the data block that is expected to be received.
Waiting for a file descriptor using poll systemcall is done with the api:
SaErrorT
saPollRetry (
struct pollfd *ufds,
unsigned int nfds,
int timeout);
where the parameters are the standard poll parameters.
Messages can be received out of order searching for a specific message id with:
----------
messages
----------
Please follow the style of the messages. It makes debugging much easier
if parallel style is used.
An service should be added to service_types enumeration in ipc_gen or in the
case of an external project, a number should be registered with the project.
enum service_types {
EVS_SERVICE = 0,
CLM_SERVICE = 1,
AMF_SERVICE = 2,
CKPT_SERVICE = 3,
EVT_SERVICE = 4,
LCK_SERVICE = 5,
MSG_SERVICE = 6,
CFG_SERVICE = 7,
CPG_SERVICE = 8
};
These are the request CLM message identifiers:
-Each library should have an ipc_APINAME.h file in include. It should define
+Each library should have an ipc_APINAME.h file in include. It should define
request types and response types.
enum req_clm_types {
MESSAGE_REQ_CLM_TRACKSTART = 0,
MESSAGE_REQ_CLM_TRACKSTOP = 1,
MESSAGE_REQ_CLM_NODEGET = 2,
MESSAGE_REQ_CLM_NODEGETASYNC = 3
};
These are the response CLM message identifiers:
enum res_clm_types {
MESSAGE_RES_CLM_TRACKCALLBACK = 0,
MESSAGE_RES_CLM_TRACKSTART = 1,
MESSAGE_RES_CLM_TRACKSTOP = 2,
MESSAGE_RES_CLM_NODEGET = 3,
MESSAGE_RES_CLM_NODEGETASYNC = 4,
MESSAGE_RES_CLM_NODEGETCALLBACK = 5
};
A request header should be placed at the front of every message send by
the library.
typedef struct {
int size __attribute__((aligned(8)));
int id __attribute__((aligned(8)));
} mar_req_header_t __attribute__((aligned(8)));
There is also a response message header which should start every response
message:
typedef struct {
int size; __attribute__((aligned(8)))
int id __attribute__((aligned(8)));
SaAisErrorT error __attribute__((aligned(8)));
} mar_res_header_t __attribute__((aligned(8)));
the error parameter is used to pass errors from the executive to the library,
including SA_ERR_TRY_AGAIN for flow control, which is described later.
This is described later:
typedef struct {
mar_uint32_t nodeid __attribute__((aligned(8)));
void *conn __attribute__((aligned(8)));
} mar_message_source_t __attribute__((aligned(8)));
This is the MESSAGE_REQ_CLM_TRACKSTART message id above:
struct req_clm_trackstart {
mar_req_header_t header;
SaUint8T trackFlags;
SaClmClusterNotificationT *notificationBufferAddress;
SaUint32T numberOfItems;
};
-The saClmClusterTrackStart api should create this message and send it to the
+The saClmClusterTrackStart api should create this message and send it to the
executive.
responses should be of:
struct res_clm_trackstart
------------
some notes
------------
-* Avoid doing anything tricky in the library itself. Let the executive
+* Avoid doing anything tricky in the library itself. Let the executive
handler do all of the work of the system. minimize what the API does.
* Once an api is developed, it must be added to the makefile. Just add
a line for the file to EXECOBJS build line.
* protect I/O send/recv with a mutex.
-* always look at other libraries when there is a question about how to
+* always look at other libraries when there is a question about how to
do something. It has likely been thought out in another library.
-------------------------------------------------------------------------------
adding services
-------------------------------------------------------------------------------
Services are defined by service handlers and messages described in
include/ipc_SERVICE.h. These two peices of information are used by the
executive to dispatch the correct messages to the correct receipients.
-------------------------------
the service handler structure
-------------------------------
A service is added by defining a structure defined in exec/service.h. The
structure is a little daunting:
struct libais_handler {
int (*libais_handler_fn) (void *conn, void *msg);
int response_size;
int response_id;
enum corosync_flow_control flow_control;
};
The response_size, response_id, and flow_control for a library handler are
used for flow control. A response message will be sent to the library of the
size response_size, with the header id of response_id if the totem message
queue is full. Some library APIs may not need to block in this condition
(because they don't have to use totem), so they should specify
COROSYNC_FLOW_CONTROL_NOT_REQUIREDin the flow control field.
The libais_handler_fn is a function to be called when the library handler is
requested to be executed.
struct corosync_exec_handler {
void (*exec_handler_fn) (void *msg, unsigned int nodeid);
void (*exec_endian_convert_fn) (void *msg);
};
The exec_handler_fn is a function to be called when the executive handler is
requested to execute.
The exec_endian_convert_fn is a function to be called to convert the endianess
of the executive message. Note messages are not stored in big or little endian
format before transmit. Instead they are transmitted in either big endian or
little endian depending on the byte order of the transmitter and converted to
the host machine order on receipt of the message.
struct corosync_service_handler {
unsigned char *name;
unsigned short id;
unsigned int private_data_size;
int (*lib_init_fn) (void *conn);
int (*lib_exit_fn) (void *conn);
struct corosync_lib_handler *lib_service;
int lib_service_count;
struct corosync_exec_handler *exec_service;
int (*exec_init_fn) (struct objdb_iface_ver0 *);
int (*config_init_fn) (struct objdb_iface_ver0 *);
void (*exec_dump_fn) (void);
int exec_service_count;
void (*confchg_fn) (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id);
void (*sync_init) (void);
int (*sync_process) (void);
void (*sync_activate) (void);
void (*sync_abort) (void);
};
name is the name of the service.
id is the identifier of the service.
private_data_size is the size of the private data used by the connection
which the library and executive handlers can reference.
lib_init_fn is the function executed when a library connection is made to
the service handler.
lib_exit_fn is the function executed when a library connection is exited
either because the application closed the file descriptor, or the OS
closed the file descriptor.
lib_service is an array of corosync_lib_handler data structures which define
the library service handler.
lib_service_count is the number of elements in lib_service.
exec_service is an array of corosync_exec_handler data structures which define
the executive service handler.
exec_init_fn is a function used to initialize the executive service. This
is only called once.
config_init_fn is called to parse config files and populate the object
database.
exec_dump_fn is called when SIGUSR2 is sent to the executive to dump the
current state of the service.
exec_service_count is the number of entries in the exec_service array.
confchg_fn is called every time a configuration change occurs.
sync_init is called when the service should begin synchronization.
sync_process is called to process synchronization messages.
sync_activate is called to activate the current service synchronization.
sync_abort is called to abort the current service synchronization.
--------------
flow control
--------------
The totem protocol includes flow control so that it doesn't send too many
messages when the network is completely full. But the library can
still send messages to the executive much faster then the executive can send
them over totem. So the library relies on the group messaging flow control to
control flow of messages sent from the library. If the totem queues are full,
no more messages may be sent, so the executive in ipc.c automatically detects
this scenario and returns an SA_ERR_TRY_AGAIN error.
When a library gets SA_ERR_TRY_AGAIN, the library may either retry, or return
this error to the user if the error is allowed by the API definitions. The
The other information is critical to ensuring that the library reads the correct
message and size of message. Make sure the libais_handler matches the messages
used in the handler function.
------------------------------------------------
dynamically linking the service handler plugin
------------------------------------------------
The service handler needs some special magic to dynamically be linked into
-corosync.
+corosync.
/*
* Dynamic loader definition
*/
static struct corosync_service_handler *clm_get_service_handler_ver0 (void);
static struct corosync_service_handler_iface_ver0 clm_service_handler_iface = {
.corosync_get_service_handler_ver0 = clm_get_service_handler_ver0
};
static struct lcr_iface corosync_clm_ver0[1] = {
{
.name = "corosync_clm",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = NULL
}
};
static struct lcr_comp clm_comp_ver0 = {
.iface_count = 1,
.ifaces = corosync_clm_ver0
};
static struct corosync_service_handler *clm_get_service_handler_ver0 (void)
{
return (&clm_service_handler);
}
__attribute__ ((constructor)) static void clm_comp_register (void) {
lcr_interfaces_set (&corosync_clm_ver0[0], &clm_service_handler_iface);
lcr_component_register (&clm_comp_ver0);
}
Once this code is added (substitute clm for the service being implemented),
the service will be loaded if its in the default services list.
The default service list is specified in service.c:default_services. If
creating an external plugin, there are configuration parameters which may
be used to add your plugin into the corosync scanning of plugins.
---------------------------------
- Connection specific information
+ Connection specific information
---------------------------------
Every connection may have specific connection information if private data
is greater then zero for the service handler. This is used to allow each
library connection to maintain private state to that connection. The private
data for a connection can be retrieved with:
struct service_pd service_pd = (struct service_pd *)corosync_conn_private_data_get (conn);
where service is the name of the service implemented and conn is the connection
information likely passed into the library handler or stored in a
message_source structure for later use by an executive handler.
------------------------------
sending responses to the api
------------------------------
A message is sent to the library from the executive message handler using
the function:
extern int corosync_conn_send_response (void *conn_info, void *msg,
int mlen);
conn_info is passed into the library message handler or stored in the
executive message. This member describes the connection to send the response.
msg is the message to send
mlen is the length of the message to send
Keep in mind that struct res_message should be at the beginning of the response
message so that it follows the style used in the rest of corosync.
--------------------------------------------
deferring response to an executive message
--------------------------------------------
The message source structure is used to store information about the source of a
message so a later executive message can respond to a library request. In
a library handler, the source field should be set up with:
message_source_set (&req_exec_ZZZZZZZ.source, conn);
gmi_mcast (req_exec_ZZZZZZZ)
In this case conn_info is passed into the library message handler
Then the executive message handler determines if this processor is responsible
for responding:
if (message_source_is_local (conn)) {
corosync_conn_send_response ();
}
---------------
Using totempg
---------------
To send a message to every processor and the local processor for self
delivery according to virtual synchrony semantics use:
The totempg interface supports multiple users at one time and if you need
to use a full totempg interface (defined in totempg.h) please ask for
assistance on the mailing list. If you simply want to use multicast
transmissions in corosync, do the following:
assert (totempg_groups_mcast_joined (corosync_group_handle, &req_exec_clm_iovec, 1, TOTEMPG_AGREED) == 0);
-----------------
library handler
-----------------
Every library handler has the prototype:
static int message_handler_req_clm_init (void *conn, void *msg);
The start of the handler function should look something like this:
int message_handler_req_clm_trackstart (void *conn *conn,
void *msg)
{
struct req_clm_trackstart *req_clm_trackstart =
(struct req_clm_trackstart *)message;
{ package up library handler message into executive message }
{ multicast message using totempg interface }
}
This assigns the void *message to a structure that can be used by the
library handler.
The conn field is used to indicate where the response should respond to.
Use the tricks described in deferring a response to the executive handler to
have the executive handler respond to the message.
avoid doing anything tricky in a library handler. Do all the work in the
executive handler at first. If later, it is possible to optimize, optimize
away.
-------------------
executive handler
-------------------
Every executive handler has the prototype:
static int message_handler_req_exec_clm_nodejoin (void *msg,
unsigned int nodeid);
The start of the handler function should look something like this:
static int message_handler_req_exec_clm_nodejoin (void *msg,
unsigned int nodeid);
{
struct req_exec_clm_nodejoin *req_exec_clm_nodejoin = (struct req_exec_clm_nodejoin *)message;
{ do real work of executing request, this is done on every node }
}
The conn_info structure is not available. If it is needed, it can be stored
in the message sent by the library message handler in a source structure.
The msg field contains the message sent by the library handler
The nodeid is a unique node identifier of the node that originated the message.
--------------------
the libais_init_fn
--------------------
This should be used to initialize any state for the connection.
--------------------
the libais_exit_fn
--------------------
This function is called every time a service connection is disconnected by
the executive. Free memory, change structures, or whatever work needs to
be done to clean up.
If the exit_fn couldn't complete because it is waiting for some event, it may
return -1, which will allow the executive to make some forward progress. Then
exit_fn will be called again. Return 0 when the exit was completed. This is
most useful when toteom should be used to queue a message, but the queue is
full. In this case, waiting a few more seconds may open up the queue, so
return -1, and then the executive will try again to call exit_fn. Do NOT
return -1 forever or the ais executive will spin.
If -1 is returned, ENSURE that the state of the library hasn't changed so much that
exit_fn cannot be called again. If exit_fn returns -1, it WILL be called again
so expect it in the code.
----------------
the confchg_fn
----------------
-This function is called whenever a configuration change occurs. Some
+This function is called whenever a configuration change occurs. Some
services may not need this function, while others may. This is a good way
to sync up joining nodes with the current state of the information stored
on a particular processor.
-------------------------------------------------------------------------------
Final comments
-------------------------------------------------------------------------------
GDB is your friend, especially the "where" command. But it stops execution.
This has a nasty side effect of killing the current configuration. In this
case GDB may become your enemy.
-printf is your friend when GDB is your enemy.
+printf is your friend when GDB is your enemy.
If stuck, ask on the mailing list, send your patches. Alot of time has been
spent designing corosync, and even more time debugging it. There are people
that can help you debug problems, especially around things like message
delivery.
Submit patches early to get feedback, especially around things like parallel
style. Parallel style is very important to ensure maintainability by the
corosync community.
If this document is wrong or incomplete, complain so we can get it fixed
for other people.
Have fun!
diff --git a/README.recovery b/README.recovery
index ceac6528..42397e81 100644
--- a/README.recovery
+++ b/README.recovery
@@ -1,116 +1,116 @@
SYNCHRONIZATION ALGORITHM:
-------------------------
The synchronization algorithm is used for every service in corosync to
synchronize state of he system.
There are 4 events of the synchronization algorithm. These events are in fact
functions that are registered in the service handler data structure. They
are called by the synchronization system whenever a network partitions or
merges.
init:
Within the init event a service handler should record temporary state variables
used by the process event.
process:
The process event is responsible for executing synchronization. This event
will return a state as to whether it has completed or not. This allows for
synchronization to be interrupted and recontinue when the message queue buffer
is full. The process event will be called again by the synchronization service
if requesed to do so by the return variable returned in process.
abort:
The abort event occurs when during synchronization a processor failure occurs.
activate:
The activate event occurs when process has returned no more processing is
necessary for any node in the cluster and all messages originated by process
have completed.
CHECKPOINT SYNCHRONIZATION ALGORITHM:
------------------------------------
The purpose of the checkpoint syncrhonization algorithm is to synchronize
checkpoints after a paritition or merge of two or more partitions. The
secondary purpose of the algorithm is to determine the cluster-wide reference
count for every checkpoint.
Every cluster contains a group of checkpoints. Each checkpoint has a
checkpoint name and checkpoint number. The number is used to uniquely reference
an unlinked but still open checkpoint in the cluser.
Every checkpoint contains a reference count which is used to determine when
that checkpoint may be released. The algorithm rebuilds the reference count
information each time a partition or merge occurs.
local variables
my_sync_state may have the values SYNC_CHECKPOINT, SYNC_REFCOUNT
my_current_iteration_state contains any data used to iterate the checkpoints
and sections.
checkpoint data
refcount_set contains reference count for every node consisting of
number of opened connections to checkpoint and node identifier
refcount contains a summation of every reference count in the refcount_set
pseudocode executed by a processor when the syncrhonization service calls
the init event
call process_checkpoints_enter
pseudocode executed by a processor when the synchronization service calls
the process event in the SYNC_CHECKPOINT state
if lowest processor identifier of old ring in new ring
transmit checkpoints or sections starting from my_current_iteration_state
if all checkpoints and sections could be queued
call sync_refcounts_enter
else
record my_current_iteration_state
require process to continue
pseudocode executed by a processor when the synchronization service calls
the process event in the SYNC_REFCOUNT state
if lowest processor identifier of old ring in new ring
transmit checkpoint reference counts
if all checkpoint reference counts could be queued
require process to not continue
else
record my_current_iteration_state for checkpoint reference counts
sync_checkpoints_enter:
my_sync_state = SYNC_CHECKPOINT
my_current_iteration_state set to start of checkpont list
sync_refcounts_enter:
my_sync_state = SYNC_REFCOUNT
on event receipt of foreign ring id message
ignore message
pseudocode executed on event receipt of checkpoint update
if checkpoint exists in temporary storage
ignore message
else
create checkpoint
reset checkpoint refcount array
-
+
pseudocode executed on event receipt of checkpoint section update
if checkpoint section exists in temporary storage
ignore message
else
create checkpoint section
pseudocode executed on event receipt of reference count update
update temporary checkpoint data storage reference count set by adding
any reference counts in the temporary message set to those from the
event
update that checkpoint's reference count
set the global checkpoint id to the current checkpoint id + 1 if it
would increase the global checkpoint id
pseudocode called when the synchronization service calls the activate event:
for all checkpoints
free all previously committed checkpoints and sections
convert temporary checkpoints and sections to regular sections
copy my_saved_ring_id to my_old_ring_id
pseudocode called when the synchronization service calls the abort event:
free all temporary checkpoints and temporary sections
diff --git a/SECURITY b/SECURITY
index 4b04094c..d1abc0c0 100644
--- a/SECURITY
+++ b/SECURITY
@@ -1,126 +1,126 @@
***
All cryptographic software in this package is subject to the following legal
notice:
This package includes publicly available encryption source code which,
together with object code resulting from the compiling of publicly
available source code, may be exported from the United States under License
Exception TSU prsuant to 15 C.F.R Section 740.13(e).
***
Security Design of corosync
The corosync project intends to mitigate the following threats:
1. forged group messaging messages which are intended to fault the corosync
executive
2. forged group messaging messages which are intended to fault applications
using corosync apis
3. monitoring of network data to capture sensitive information
The corosync project does not intend to mitigate the following threats:
1. physical access to the hardware which could expose the private key
2. privledged access to the operating system which could expose the private key
or be used to inject errors into the ais executive.
3. library user creates requests which are intended to fault the corosync
executive
The corosync project mitigates the threats using two mechanisms:
1. Authentication
2. Secrecy
Library Interface
-----------------
The corosync executive authenticates every library user. The library is only
allowed to access services if it's GID is ais or 0. Unauthorized library
users are rejected.
The ais group is a trusted group. If the administrator doesn't trust the
application, it should not be added to the group! Any member of the ais group
could potentially send a malformed request to the executive and cause it to
fault.
Group Messaging Interface
-------------------------
Group messaging uses UDP/IP to communicate with other corosync executives using
messages. It is possible without authentication of every packet that an
attacker could forge messages. These forged messages could fault the corosync
-executive distributed state machines. It would also be possible to corrupt
+executive distributed state machines. It would also be possible to corrupt
end applications by forging changes.
Since messages are sent using UDP/IP it would be possible to snoop those
messages and rebuild sensitive data.
To solve these problems, the group messaging interface uses two new interfaces
interal to it's implementation:
1. encrypt_and_sign - encrypts and signs a message securely
2. authenticate_and_decrypt - authenticates and decrypts a message securely
When the executive wants to send a message over the network, it uses
encrypt_and_sign to prepare the message to be sent. When the executive
wants to receive a message from the network, it uses
authenticate_and_decrypt to verify the message is valid and decrypt it.
These two functions utilize the following algorithms:
-sha1 - hash algorithm secure for using with hmac
+sha1 - hash algorithm secure for using with hmac
hmac - produces a 16 byte digest from any length input
sober - pseudo random number generator and stream cipher
The hmac algorithm requires a 16 byte key.
The sober algorithm requires a 16 byte private key.
The sober algorithm requires a 16 byte public initial vector.
The private key is read from disk and stored in memory for use with the
sober algorithm to generate the three required keys.
Every message starts with a
struct security {
unsigned char digest[20]; A one way hash digest
- unsigned char salt[16]; A securely generated random number
+ unsigned char salt[16]; A securely generated random number
}
When a message is sent (encrypt_and_sign):
------------------------------------------
1. sober is used to create a 16 byte random number (salt) using the md4
algorithm
2. sober is keyed with the private key and the initial vector is set to the
salt. Then a 48 byte key is read from the sober algorithm. This 48 byte
key is split into 3 16 byte keys. The keys are the hmac key, the sober key
and the sober initial vector.
3. A sober instance is keyed with the sober key and sober initial vector
from step #2.
4. The data of the packet, except for the security header, is encrypted using
the sober cipher that was initialized in step #3.
5. The salt is stored in the security header of the outgoing message.
6. The hmac is initialized with the hmac key generated in step #2.
7. The message, except for the security header, is hmaced to produce a digest
using the sha1 algorithm.
8. The digest is stored in the outgoing message.
-9. The message is transmitted.
+9. The message is transmitted.
When a message is received (decrypt_and_authenticate):
------------------------------------------------------
1. sober is keyed with the private key and the initial vector is set to the
salt in the received message. Then a 48 byte key is read from the sober
algorithm. This 48 byte key is split into 3 16 byte keys. The keys are the
hmac key, the sober key and the sober initial vector.
2. The sober key and sober initial vector from step #1 are used to key a
new sober instance.
3. The hmac is setup using the hmac key generated in step #1 using sha1.
5. The message is authenticated, except for the security header.
6. If the message was not authenticated, the caller is told of the result.
The caller ignores the message.
7. The message is decrypted, except for the security header, using the sober
algorithm in step #2.
8. The message is processed.
This does consume some resources. It ensures the private key is never shared
openly, that messages are authenticated, that messages are encrypted, and that
any key exposure of the sober encryption key, sober initial vector, or hmac
key can only be used to attack one of the algorithms. Finally every key used
is randomly unique (within the 2^128 search space of the input to sober) to
ensure that keys are never reused, nonce's are never reused, and hmac's are
never reused.
Comments welcome mailto:corosync@lists.osdl.org
diff --git a/autogen.sh b/autogen.sh
index c1b7181c..27a60724 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,129 +1,129 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
testProgram()
{
cmd=$1
if [ -z "$cmd" ]; then
return 1;
fi
arch=`uname -s`
# Make sure the which is in an if-block... on some platforms it throws exceptions
#
# The ERR trap is not executed if the failed command is part
# of an until or while loop, part of an if statement, part of a &&
# or || list.
if
which $cmd </dev/null >/dev/null 2>&1
then
:
else
return 1
fi
# The GNU standard is --version
- if
+ if
$cmd --version </dev/null >/dev/null 2>&1
then
- return 0
+ return 0
fi
# Maybe it suppports -V instead
- if
+ if
$cmd -V </dev/null >/dev/null 2>&1
then
- return 0
+ return 0
fi
# Nope, the program seems broken
return 1
}
arch=`uname -s`
# Disable the errors on FreeBSD until a fix can be found.
if [ ! "$arch" = "FreeBSD" ]; then
set -e
#
# All errors are fatal from here on out...
# The shell will complain and exit on any "uncaught" error code.
#
#
# And the trap will ensure sure some kind of error message comes out.
#
trap 'echo ""; echo "$0 exiting due to error (sorry!)." >&2' 0
fi
RC=0
gnu="ftp://ftp.gnu.org/pub/gnu"
# Check for Autoconf
-for command in autoconf autoconf213 autoconf253 autoconf259
+for command in autoconf autoconf213 autoconf253 autoconf259
do
if
testProgram $command == 1
then
autoconf=$command
autoheader=`echo "$autoconf" | sed -e 's/autoconf/autoheader/'`
autom4te=`echo "$autoconf" | sed -e 's/autoconf/autmo4te/'`
autoreconf=`echo "$autoconf" | sed -e 's/autoconf/autoreconf/'`
autoscan=`echo "$autoconf" | sed -e 's/autoconf/autoscan/'`
autoupdate=`echo "$autoconf" | sed -e 's/autoconf/autoupdate/'`
ifnames=`echo "$autoconf" | sed -e 's/autoconf/ifnames/'`
fi
done
# Check for automake
for command in automake19 automake-1.9 automake
do
- if
+ if
testProgram $command
then
automake=$command
aclocal=`echo "$automake" | sed -e 's/automake/aclocal/'`
fi
done
-if [ -z $autoconf ]; then
+if [ -z $autoconf ]; then
echo You must have autoconf installed to compile the corosync package.
echo Download the appropriate package for your system,
echo or get the source tarball at: $gnu/autoconf/
exit 1
-elif [ -z $automake ]; then
+elif [ -z $automake ]; then
echo You must have automake installed to compile the corosync package.
echo Download the appropriate package for your system,
echo or get the source tarball at: $gnu/automake/
exit 1
fi
# Create local copies so that the incremental updates will work.
rm -f ./autoconf ./automake ./autoheader
ln -s `which $autoconf` ./autoconf
ln -s `which $automake` ./automake
ln -s `which $autoheader` ./autoheader
printf "$autoconf:\t"
-$autoconf --version | head -n 1
+$autoconf --version | head -n 1
printf "$automake:\t"
$automake --version | head -n 1
echo $aclocal $ACLOCAL_FLAGS
$aclocal $ACLOCAL_FLAGS
echo $autoheader
$autoheader
echo $automake --add-missing --include-deps --copy
$automake --add-missing --include-deps --copy
echo $autoconf
$autoconf
echo Now run ./configure
trap '' 0
diff --git a/exec/Makefile.am b/exec/Makefile.am
index 61e0c153..eec9ffe2 100644
--- a/exec/Makefile.am
+++ b/exec/Makefile.am
@@ -1,137 +1,137 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
AM_CFLAGS = -fPIC
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
TOTEM_SRC = coropoll.c totemip.c totemnet.c totemrrp.c \
totemsrp.c totemmrp.c totempg.c crypto.c wthread.c
LOGSYS_SRC = wthread.c logsys.c
COROIPCS_SRC = coroipcs.c coroipcs.h
LCRSO_SRC = objdb.c vsf_ykd.c coroparse.c quorum.c vsf_quorum.c
LCRSO_OBJS = $(LCRSO_SRC:%.c=%.o)
LCRSO = $(LCRSO_SRC:%.c=%.lcrso)
lib_LIBRARIES = libtotem_pg.a liblogsys.a libcoroipcs.a
sbin_PROGRAMS = corosync
libtotem_pg_a_SOURCES = $(TOTEM_SRC)
liblogsys_a_SOURCES = $(LOGSYS_SRC)
libcoroipcs_a_SOURCES = $(COROIPCS_SRC)
corosync_SOURCES = main.c mempool.c util.c sync.c apidef.c service.c \
timer.c totemconfig.c mainconfig.c quorum.c schedwrk.c \
../lcr/lcr_ifact.c
corosync_LDADD = -ltotem_pg -llogsys -lcoroipcs
corosync_DEPENDENCIES = libtotem_pg.so.$(SONAME) liblogsys.so.$(SONAME) libcoroipcs.so.$(SONAME)
corosync_LDFLAGS = $(OS_DYFLAGS) -L./
TOTEM_OBJS = $(TOTEM_SRC:%.c=%.o)
LOGSYS_OBJS = $(LOGSYS_SRC:%.c=%.o)
COROIPCS_OBJS = $(COROIPCS_SRC:%.c=%.o)
SHARED_LIBS = $(lib_LIBRARIES:%.a=%.so.$(SONAME))
SHARED_LIBS_SO = $(SHARED_LIBS:%.so.$(SONAME)=%.so)
SHARED_LIBS_SO_TWO = $(SHARED_LIBS:%.so.$(SONAME)=%.so.$(SOMAJOR))
noinst_HEADERS = apidef.h crypto.h mainconfig.h main.h mempool.h \
quorum.h service.h sync.h timer.h tlist.h totemconfig.h \
totemmrp.h totemnet.h totemrrp.h totemsrp.h util.h \
version.h vsf.h wthread.h schedwrk.h
EXTRA_DIST = $(LCRSO_SRC)
if BUILD_DARWIN
%.lcrso: %.o
$(CC) $(CFLAGS) -bundle -bind_at_load -bundle_loader ./corosync $^ -o $@
libtotem_pg.so.$(SONAME): $(TOTEM_OBJS)
$(CC) $(LDFLAGS) $(DARWIN_OPTS) $(TOTEM_OBJS) -o $@ -lpthread
liblogsys.so.$(SONAME): $(LOGSYS_OBJS)
$(CC) $(LDFLAGS) $(DARWIN_OPTS) $(LOGSYS_OBJS) -o $@ -lpthread
libcoroipcs.so.$(SONAME): $(COROIPCS_OBJS)
$(CC) $(LDFLAGS) $(DARWIN_OPTS) $(COROIPCS_OBJS) -o $@ -lpthread
else
%.lcrso: %.o
$(CC) $(CFLAGS) -shared -Wl,-soname=$@ $^ -o $@
libtotem_pg.so.$(SONAME): $(TOTEM_OBJS)
$(CC) -shared -o $@ \
-Wl,-soname=libtotem_pg.so.$(SOMAJOR) \
$^ $(LDFLAGS) -lpthread
ln -sf libtotem_pg.so.$(SONAME) libtotem_pg.so
ln -sf libtotem_pg.so.$(SONAME) libtotem_pg.so.$(SOMAJOR)
liblogsys.so.$(SONAME): $(LOGSYS_OBJS)
$(CC) -shared -o $@ \
-Wl,-soname=liblogsys.so.$(SOMAJOR) \
$^ $(LDFLAGS) -lpthread
ln -sf liblogsys.so.$(SONAME) liblogsys.so
ln -sf liblogsys.so.$(SONAME) liblogsys.so.$(SOMAJOR)
libcoroipcs.so.$(SONAME): $(COROIPCS_OBJS)
$(CC) -shared -o $@ \
-Wl,-soname=libcoroipcs.so.$(SOMAJOR) \
$^ $(LDFLAGS) -lpthread
ln -sf libcoroipcs.so.$(SONAME) libcoroipcs.so
ln -sf libcoroipcs.so.$(SONAME) libcoroipcs.so.$(SOMAJOR)
endif
lint:
-splint $(LINT_FLAGS) $(CFLAGS) *.c
all-local: $(LCRSO_OBJS) $(LCRSO) $(SHARED_LIBS)
@echo Built corosync Executive
install-exec-local:
$(INSTALL) -d $(DESTDIR)/$(libdir)
$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
cp -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
$(INSTALL) -d $(DESTDIR)/$(LCRSODIR)
$(INSTALL) -m 755 $(LCRSO) $(DESTDIR)/$(LCRSODIR)
uninstall-local:
cd $(DESTDIR)/$(libdir) && \
rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
cd $(DESTDIR)/$(LCRSODIR) && \
rm -f $(LCRSO)
clean-local:
rm -f corosync *.o *.lcrso gmon.out *.da *.bb *.bbg *.so*
diff --git a/exec/coroipcs.c b/exec/coroipcs.c
index 10e158b5..228de3b9 100644
--- a/exec/coroipcs.c
+++ b/exec/coroipcs.c
@@ -1,1386 +1,1386 @@
/*
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <pthread.h>
#include <assert.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#if defined(HAVE_GETPEERUCRED)
#include <ucred.h>
#endif
#include <sys/shm.h>
#include <sys/sem.h>
#include <corosync/corotypes.h>
#include <corosync/list.h>
#include "coroipcs.h"
#include <corosync/ipc_gen.h>
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#define SERVER_BACKLOG 5
#define MSG_SEND_LOCKED 0
#define MSG_SEND_UNLOCKED 1
static struct coroipcs_init_state *api;
DECLARE_LIST_INIT (conn_info_list_head);
struct outq_item {
void *msg;
size_t mlen;
struct list_head list;
};
struct zcb_mapped {
struct list_head list;
void *addr;
size_t size;
};
#if defined(_SEM_SEMUN_UNDEFINED)
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif
enum conn_state {
CONN_STATE_THREAD_INACTIVE = 0,
CONN_STATE_THREAD_ACTIVE = 1,
CONN_STATE_THREAD_REQUEST_EXIT = 2,
CONN_STATE_THREAD_DESTROYED = 3,
CONN_STATE_LIB_EXIT_CALLED = 4,
CONN_STATE_DISCONNECT_INACTIVE = 5
};
struct conn_info {
int fd;
pthread_t thread;
pthread_attr_t thread_attr;
unsigned int service;
enum conn_state state;
int notify_flow_control_enabled;
int refcount;
key_t shmkey;
key_t semkey;
int semid;
unsigned int pending_semops;
pthread_mutex_t mutex;
struct control_buffer *control_buffer;
char *request_buffer;
char *response_buffer;
char *dispatch_buffer;
size_t control_size;
size_t request_size;
size_t response_size;
size_t dispatch_size;
struct list_head outq_head;
void *private_data;
struct list_head list;
char setup_msg[sizeof (mar_req_setup_t)];
unsigned int setup_bytes_read;
struct list_head zcb_mapped_list_head;
char *sending_allowed_private_data[64];
};
static int shared_mem_dispatch_bytes_left (const struct conn_info *conn_info);
static void outq_flush (struct conn_info *conn_info);
static int priv_change (struct conn_info *conn_info);
static void ipc_disconnect (struct conn_info *conn_info);
static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
int locked);
static int
memory_map (
const char *path,
size_t bytes,
void **buf)
{
int fd;
void *addr_orig;
void *addr;
int res;
-
+
fd = open (path, O_RDWR, 0600);
unlink (path);
res = ftruncate (fd, bytes);
addr_orig = mmap (NULL, bytes, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
+
if (addr_orig == MAP_FAILED) {
return (-1);
}
-
+
addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
-
+
if (addr != addr_orig) {
return (-1);
}
-
+
res = close (fd);
if (res) {
return (-1);
}
*buf = addr_orig;
return (0);
}
static int
circular_memory_map (
const char *path,
size_t bytes,
void **buf)
{
int fd;
void *addr_orig;
void *addr;
int res;
-
+
fd = open (path, O_RDWR, 0600);
unlink (path);
res = ftruncate (fd, bytes);
addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
+
if (addr_orig == MAP_FAILED) {
return (-1);
}
-
+
addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
-
+
if (addr != addr_orig) {
return (-1);
}
-
+
addr = mmap (((char *)addr_orig) + bytes,
bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
-
+
res = close (fd);
if (res) {
return (-1);
}
*buf = addr_orig;
return (0);
}
static inline int
circular_memory_unmap (void *buf, size_t bytes)
{
int res;
res = munmap (buf, bytes << 1);
return (res);
}
static inline int zcb_free (struct zcb_mapped *zcb_mapped)
{
unsigned int res;
res = munmap (zcb_mapped->addr, zcb_mapped->size);
list_del (&zcb_mapped->list);
free (zcb_mapped);
return (res);
}
static inline int zcb_by_addr_free (struct conn_info *conn_info, void *addr)
{
struct list_head *list;
struct zcb_mapped *zcb_mapped;
unsigned int res = 0;
for (list = conn_info->zcb_mapped_list_head.next;
list != &conn_info->zcb_mapped_list_head; list = list->next) {
zcb_mapped = list_entry (list, struct zcb_mapped, list);
if (zcb_mapped->addr == addr) {
res = zcb_free (zcb_mapped);
break;
}
}
return (res);
}
static inline int zcb_all_free (
struct conn_info *conn_info)
{
struct list_head *list;
struct zcb_mapped *zcb_mapped;
for (list = conn_info->zcb_mapped_list_head.next;
list != &conn_info->zcb_mapped_list_head;) {
zcb_mapped = list_entry (list, struct zcb_mapped, list);
list = list->next;
zcb_free (zcb_mapped);
}
return (0);
}
static inline int zcb_alloc (
struct conn_info *conn_info,
const char *path_to_file,
size_t size,
void **addr)
{
struct zcb_mapped *zcb_mapped;
unsigned int res;
zcb_mapped = malloc (sizeof (struct zcb_mapped));
if (zcb_mapped == NULL) {
return (-1);
}
res = memory_map (
path_to_file,
size,
addr);
if (res == -1) {
return (-1);
}
list_init (&zcb_mapped->list);
zcb_mapped->addr = *addr;
zcb_mapped->size = size;
list_add_tail (&zcb_mapped->list, &conn_info->zcb_mapped_list_head);
return (0);
}
static int ipc_thread_active (void *conn)
{
struct conn_info *conn_info = (struct conn_info *)conn;
int retval = 0;
pthread_mutex_lock (&conn_info->mutex);
if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
retval = 1;
}
pthread_mutex_unlock (&conn_info->mutex);
return (retval);
}
static int ipc_thread_exiting (void *conn)
{
struct conn_info *conn_info = (struct conn_info *)conn;
int retval = 1;
pthread_mutex_lock (&conn_info->mutex);
if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
retval = 0;
} else
if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
retval = 0;
}
pthread_mutex_unlock (&conn_info->mutex);
return (retval);
}
/*
* returns 0 if should be called again, -1 if finished
*/
static inline int conn_info_destroy (struct conn_info *conn_info)
{
unsigned int res;
void *retval;
list_del (&conn_info->list);
list_init (&conn_info->list);
if (conn_info->state == CONN_STATE_THREAD_REQUEST_EXIT) {
res = pthread_join (conn_info->thread, &retval);
conn_info->state = CONN_STATE_THREAD_DESTROYED;
return (0);
}
if (conn_info->state == CONN_STATE_THREAD_INACTIVE ||
conn_info->state == CONN_STATE_DISCONNECT_INACTIVE) {
list_del (&conn_info->list);
close (conn_info->fd);
api->free (conn_info);
return (-1);
}
if (conn_info->state == CONN_STATE_THREAD_ACTIVE) {
pthread_kill (conn_info->thread, SIGUSR1);
return (0);
}
api->serialize_lock ();
/*
* Retry library exit function if busy
*/
if (conn_info->state == CONN_STATE_THREAD_DESTROYED) {
res = api->exit_fn_get (conn_info->service) (conn_info);
if (res == -1) {
api->serialize_unlock ();
return (0);
} else {
conn_info->state = CONN_STATE_LIB_EXIT_CALLED;
}
}
pthread_mutex_lock (&conn_info->mutex);
if (conn_info->refcount > 0) {
pthread_mutex_unlock (&conn_info->mutex);
api->serialize_unlock ();
return (0);
}
list_del (&conn_info->list);
pthread_mutex_unlock (&conn_info->mutex);
/*
* Destroy shared memory segment and semaphore
*/
res = munmap (conn_info->control_buffer, conn_info->control_size);
res = munmap (conn_info->request_buffer, conn_info->request_size);
res = munmap (conn_info->response_buffer, conn_info->response_size);
semctl (conn_info->semid, 0, IPC_RMID);
/*
* Free allocated data needed to retry exiting library IPC connection
*/
if (conn_info->private_data) {
api->free (conn_info->private_data);
}
close (conn_info->fd);
res = circular_memory_unmap (conn_info->dispatch_buffer, conn_info->dispatch_size);
zcb_all_free (conn_info);
api->free (conn_info);
api->serialize_unlock ();
return (-1);
}
struct res_overlay {
mar_res_header_t header __attribute__((aligned(8)));
char buf[4096];
};
union u {
uint64_t server_addr;
void *server_ptr;
};
static uint64_t void2serveraddr (void *server_ptr)
{
union u u;
u.server_ptr = server_ptr;
return (u.server_addr);
}
static void *serveraddr2void (uint64_t server_addr)
{
union u u;
u.server_addr = server_addr;
return (u.server_ptr);
-};
+};
static inline void zerocopy_operations_process (
struct conn_info *conn_info,
mar_req_header_t **header_out,
unsigned int *new_message)
{
mar_req_header_t *header;
header = (mar_req_header_t *)conn_info->request_buffer;
if (header->id == ZC_ALLOC_HEADER) {
mar_req_coroipcc_zc_alloc_t *hdr = (mar_req_coroipcc_zc_alloc_t *)header;
mar_res_header_t res_header;
void *addr = NULL;
struct coroipcs_zc_header *zc_header;
unsigned int res;
res = zcb_alloc (conn_info, hdr->path_to_file, hdr->map_size,
&addr);
zc_header = (struct coroipcs_zc_header *)addr;
zc_header->server_address = void2serveraddr(addr);
res_header.size = sizeof (mar_res_header_t);
res_header.id = 0;
coroipcs_response_send (
- conn_info, &res_header,
+ conn_info, &res_header,
res_header.size);
*new_message = 0;
return;
- } else
+ } else
if (header->id == ZC_FREE_HEADER) {
mar_req_coroipcc_zc_free_t *hdr = (mar_req_coroipcc_zc_free_t *)header;
mar_res_header_t res_header;
void *addr = NULL;
addr = serveraddr2void (hdr->server_address);
zcb_by_addr_free (conn_info, addr);
res_header.size = sizeof (mar_res_header_t);
res_header.id = 0;
coroipcs_response_send (
- conn_info, &res_header,
+ conn_info, &res_header,
res_header.size);
*new_message = 0;
return;
- } else
+ } else
if (header->id == ZC_EXECUTE_HEADER) {
mar_req_coroipcc_zc_execute_t *hdr = (mar_req_coroipcc_zc_execute_t *)header;
-
+
header = (mar_req_header_t *)(((char *)serveraddr2void(hdr->server_address) + sizeof (struct coroipcs_zc_header)));
}
*header_out = header;
*new_message = 1;
}
static void *pthread_ipc_consumer (void *conn)
{
struct conn_info *conn_info = (struct conn_info *)conn;
struct sembuf sop;
int res;
mar_req_header_t *header;
struct res_overlay res_overlay;
int send_ok;
unsigned int new_message;
if (api->sched_priority != 0) {
struct sched_param sched_param;
sched_param.sched_priority = api->sched_priority;
res = pthread_setschedparam (conn_info->thread, SCHED_RR, &sched_param);
}
for (;;) {
sop.sem_num = 0;
sop.sem_op = -1;
sop.sem_flg = 0;
retry_semop:
if (ipc_thread_active (conn_info) == 0) {
coroipcs_refcount_dec (conn_info);
pthread_exit (0);
}
res = semop (conn_info->semid, &sop, 1);
if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
goto retry_semop;
} else
if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
coroipcs_refcount_dec (conn_info);
pthread_exit (0);
}
zerocopy_operations_process (conn_info, &header, &new_message);
/*
* There is no new message to process, continue for loop
*/
if (new_message == 0) {
continue;
}
coroipcs_refcount_inc (conn);
send_ok = api->sending_allowed (conn_info->service,
header->id,
- header,
+ header,
conn_info->sending_allowed_private_data);
-
+
if (send_ok) {
api->serialize_lock();
api->handler_fn_get (conn_info->service, header->id) (conn_info, header);
api->serialize_unlock();
} else {
/*
* Overload, tell library to retry
*/
res_overlay.header.size =
api->response_size_get (conn_info->service, header->id);
res_overlay.header.id =
api->response_id_get (conn_info->service, header->id);
res_overlay.header.error = CS_ERR_TRY_AGAIN;
- coroipcs_response_send (conn_info, &res_overlay,
+ coroipcs_response_send (conn_info, &res_overlay,
res_overlay.header.size);
}
api->sending_allowed_release (conn_info->sending_allowed_private_data);
coroipcs_refcount_dec (conn);
}
pthread_exit (0);
}
static int
req_setup_send (
struct conn_info *conn_info,
int error)
{
mar_res_setup_t res_setup;
unsigned int res;
res_setup.error = error;
retry_send:
res = send (conn_info->fd, &res_setup, sizeof (mar_res_setup_t), MSG_WAITALL);
if (res == -1 && errno == EINTR) {
goto retry_send;
} else
if (res == -1 && errno == EAGAIN) {
goto retry_send;
}
return (0);
}
static int
req_setup_recv (
struct conn_info *conn_info)
{
int res;
struct msghdr msg_recv;
struct iovec iov_recv;
#ifdef COROSYNC_LINUX
struct cmsghdr *cmsg;
char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))];
struct ucred *cred;
int off = 0;
int on = 1;
#endif
msg_recv.msg_iov = &iov_recv;
msg_recv.msg_iovlen = 1;
msg_recv.msg_name = 0;
msg_recv.msg_namelen = 0;
#ifdef COROSYNC_LINUX
msg_recv.msg_control = (void *)cmsg_cred;
msg_recv.msg_controllen = sizeof (cmsg_cred);
#endif
#ifdef PORTABILITY_WORK_TODO
#ifdef COROSYNC_SOLARIS
msg_recv.msg_flags = 0;
uid_t euid;
gid_t egid;
-
+
euid = -1;
egid = -1;
if (getpeereid(conn_info->fd, &euid, &egid) != -1 &&
(api->security_valid (euid, egid)) {
if (conn_info->state == CONN_IO_STATE_INITIALIZING) {
api->log_printf ("Invalid security authentication\n");
return (-1);
}
}
msg_recv.msg_accrights = 0;
msg_recv.msg_accrightslen = 0;
#else /* COROSYNC_SOLARIS */
#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 (api->security_valid (euid, egid) {
conn_info->authenticated = 1;
}
ucred_free(uc);
}
if (conn_info->authenticated == 0) {
api->log_printf ("Invalid security authentication\n");
}
#else /* HAVE_GETPEERUCRED */
api->log_printf (LOGSYS_LEVEL_SECURITY, "Connection not authenticated "
"because platform does not support "
"authentication with sockets, continuing "
"with a fake authentication\n");
#endif /* HAVE_GETPEERUCRED */
#endif /* COROSYNC_SOLARIS */
#endif
iov_recv.iov_base = &conn_info->setup_msg[conn_info->setup_bytes_read];
iov_recv.iov_len = sizeof (mar_req_setup_t) - conn_info->setup_bytes_read;
#ifdef COROSYNC_LINUX
setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
#endif
retry_recv:
res = recvmsg (conn_info->fd, &msg_recv, MSG_NOSIGNAL);
if (res == -1 && errno == EINTR) {
goto retry_recv;
} else
if (res == -1 && errno != EAGAIN) {
return (0);
} else
if (res == 0) {
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
/* On many OS poll never return POLLHUP or POLLERR.
* EOF is detected when recvmsg return 0.
*/
ipc_disconnect (conn_info);
#endif
return (-1);
}
conn_info->setup_bytes_read += res;
#ifdef COROSYNC_LINUX
cmsg = CMSG_FIRSTHDR (&msg_recv);
assert (cmsg);
cred = (struct ucred *)CMSG_DATA (cmsg);
if (cred) {
if (api->security_valid (cred->uid, cred->gid)) {
} else {
ipc_disconnect (conn_info);
api->log_printf ("Invalid security authentication\n");
return (-1);
}
}
#endif
if (conn_info->setup_bytes_read == sizeof (mar_req_setup_t)) {
#ifdef COROSYNC_LINUX
setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED,
&off, sizeof (off));
#endif
return (1);
}
return (0);
}
static void ipc_disconnect (struct conn_info *conn_info)
{
if (conn_info->state == CONN_STATE_THREAD_INACTIVE) {
conn_info->state = CONN_STATE_DISCONNECT_INACTIVE;
return;
}
if (conn_info->state != CONN_STATE_THREAD_ACTIVE) {
return;
}
pthread_mutex_lock (&conn_info->mutex);
conn_info->state = CONN_STATE_THREAD_REQUEST_EXIT;
pthread_mutex_unlock (&conn_info->mutex);
pthread_kill (conn_info->thread, SIGUSR1);
}
static int conn_info_create (int fd)
{
struct conn_info *conn_info;
conn_info = api->malloc (sizeof (struct conn_info));
if (conn_info == NULL) {
return (-1);
}
memset (conn_info, 0, sizeof (struct conn_info));
conn_info->fd = fd;
conn_info->service = SOCKET_SERVICE_INIT;
conn_info->state = CONN_STATE_THREAD_INACTIVE;
list_init (&conn_info->outq_head);
list_init (&conn_info->list);
list_init (&conn_info->zcb_mapped_list_head);
list_add (&conn_info->list, &conn_info_list_head);
api->poll_dispatch_add (fd, conn_info);
return (0);
}
#if defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS)
/* SUN_LEN is broken for abstract namespace
*/
#define COROSYNC_SUN_LEN(a) sizeof(*(a))
#else
#define COROSYNC_SUN_LEN(a) SUN_LEN(a)
#endif
/*
* Exported functions
*/
extern void coroipcs_ipc_init (
struct coroipcs_init_state *init_state)
{
int server_fd;
struct sockaddr_un un_addr;
int res;
api = init_state;
/*
* Create socket for IPC clients, name socket, listen for connections
*/
server_fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (server_fd == -1) {
api->log_printf ("Cannot create client connections socket.\n");
api->fatal_error ("Can't create library listen socket");
};
res = fcntl (server_fd, F_SETFL, O_NONBLOCK);
if (res == -1) {
api->log_printf ("Could not set non-blocking operation on server socket: %s\n", strerror (errno));
api->fatal_error ("Could not set non-blocking operation on server socket");
}
memset (&un_addr, 0, sizeof (struct sockaddr_un));
un_addr.sun_family = AF_UNIX;
#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
un_addr.sun_len = sizeof(struct sockaddr_un);
#endif
#if defined(COROSYNC_LINUX)
sprintf (un_addr.sun_path + 1, "%s", api->socket_name);
#else
sprintf (un_addr.sun_path, "%s/%s", SOCKETDIR, api->socket_name);
unlink (un_addr.sun_path);
#endif
res = bind (server_fd, (struct sockaddr *)&un_addr, COROSYNC_SUN_LEN(&un_addr));
if (res) {
api->log_printf ("Could not bind AF_UNIX: %s.\n", strerror (errno));
api->fatal_error ("Could not bind to AF_UNIX socket\n");
}
listen (server_fd, SERVER_BACKLOG);
/*
* Setup connection dispatch routine
*/
api->poll_accept_add (server_fd);
}
void coroipcs_ipc_exit (void)
{
struct list_head *list;
struct conn_info *conn_info;
unsigned int res;
for (list = conn_info_list_head.next; list != &conn_info_list_head;
list = list->next) {
conn_info = list_entry (list, struct conn_info, list);
/*
* Unmap memory segments
*/
res = munmap (conn_info->control_buffer,
conn_info->control_size);
res = munmap (conn_info->request_buffer,
conn_info->request_size);
res = munmap (conn_info->response_buffer,
conn_info->response_size);
res = circular_memory_unmap (conn_info->dispatch_buffer,
conn_info->dispatch_size);
semctl (conn_info->semid, 0, IPC_RMID);
-
+
pthread_kill (conn_info->thread, SIGUSR1);
}
}
/*
* Get the conn info private data
*/
void *coroipcs_private_data_get (void *conn)
{
struct conn_info *conn_info = (struct conn_info *)conn;
return (conn_info->private_data);
}
int coroipcs_response_send (void *conn, const void *msg, size_t mlen)
{
struct conn_info *conn_info = (struct conn_info *)conn;
struct sembuf sop;
int res;
memcpy (conn_info->response_buffer, msg, mlen);
sop.sem_num = 1;
sop.sem_op = 1;
sop.sem_flg = 0;
retry_semop:
res = semop (conn_info->semid, &sop, 1);
if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
goto retry_semop;
} else
if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
return (0);
}
return (0);
}
int coroipcs_response_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
{
struct conn_info *conn_info = (struct conn_info *)conn;
struct sembuf sop;
int res;
int write_idx = 0;
int i;
for (i = 0; i < iov_len; i++) {
memcpy (&conn_info->response_buffer[write_idx],
iov[i].iov_base, iov[i].iov_len);
write_idx += iov[i].iov_len;
}
sop.sem_num = 1;
sop.sem_op = 1;
sop.sem_flg = 0;
retry_semop:
res = semop (conn_info->semid, &sop, 1);
if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
goto retry_semop;
} else
if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
return (0);
}
return (0);
}
static int shared_mem_dispatch_bytes_left (const struct conn_info *conn_info)
{
unsigned int n_read;
unsigned int n_write;
unsigned int bytes_left;
n_read = conn_info->control_buffer->read;
n_write = conn_info->control_buffer->write;
if (n_read <= n_write) {
bytes_left = conn_info->dispatch_size - n_write + n_read;
} else {
bytes_left = n_read - n_write;
}
return (bytes_left);
}
static void memcpy_dwrap (struct conn_info *conn_info, void *msg, unsigned int len)
{
unsigned int write_idx;
write_idx = conn_info->control_buffer->write;
memcpy (&conn_info->dispatch_buffer[write_idx], msg, len);
conn_info->control_buffer->write = (write_idx + len) % conn_info->dispatch_size;
}
static void msg_send (void *conn, const struct iovec *iov, unsigned int iov_len,
int locked)
{
struct conn_info *conn_info = (struct conn_info *)conn;
struct sembuf sop;
int res;
int i;
char buf;
for (i = 0; i < iov_len; i++) {
memcpy_dwrap (conn_info, iov[i].iov_base, iov[i].iov_len);
}
buf = !list_empty (&conn_info->outq_head);
res = send (conn_info->fd, &buf, 1, MSG_NOSIGNAL);
if (res == -1 && errno == EAGAIN) {
if (locked == 0) {
pthread_mutex_lock (&conn_info->mutex);
}
conn_info->pending_semops += 1;
if (locked == 0) {
pthread_mutex_unlock (&conn_info->mutex);
}
api->poll_dispatch_modify (conn_info->fd,
POLLIN|POLLOUT|POLLNVAL);
} else
if (res == -1) {
ipc_disconnect (conn_info);
}
sop.sem_num = 2;
sop.sem_op = 1;
sop.sem_flg = 0;
retry_semop:
res = semop (conn_info->semid, &sop, 1);
if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
goto retry_semop;
} else
if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
return;
}
}
static void outq_flush (struct conn_info *conn_info) {
struct list_head *list, *list_next;
struct outq_item *outq_item;
unsigned int bytes_left;
struct iovec iov;
char buf;
int res;
pthread_mutex_lock (&conn_info->mutex);
if (list_empty (&conn_info->outq_head)) {
buf = 3;
res = send (conn_info->fd, &buf, 1, MSG_NOSIGNAL);
pthread_mutex_unlock (&conn_info->mutex);
return;
}
for (list = conn_info->outq_head.next;
list != &conn_info->outq_head; list = list_next) {
list_next = list->next;
outq_item = list_entry (list, struct outq_item, list);
bytes_left = shared_mem_dispatch_bytes_left (conn_info);
if (bytes_left > outq_item->mlen) {
iov.iov_base = outq_item->msg;
iov.iov_len = outq_item->mlen;
msg_send (conn_info, &iov, 1, MSG_SEND_UNLOCKED);
list_del (list);
api->free (iov.iov_base);
api->free (outq_item);
} else {
break;
}
}
pthread_mutex_unlock (&conn_info->mutex);
}
static int priv_change (struct conn_info *conn_info)
{
mar_req_priv_change req_priv_change;
unsigned int res;
union semun semun;
struct semid_ds ipc_set;
int i;
retry_recv:
res = recv (conn_info->fd, &req_priv_change,
sizeof (mar_req_priv_change),
MSG_NOSIGNAL);
if (res == -1 && errno == EINTR) {
goto retry_recv;
}
if (res == -1 && errno == EAGAIN) {
goto retry_recv;
}
if (res == -1 && errno != EAGAIN) {
return (-1);
}
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
/* Error on socket, EOF is detected when recv return 0
*/
if (res == 0) {
return (-1);
}
#endif
ipc_set.sem_perm.uid = req_priv_change.euid;
ipc_set.sem_perm.gid = req_priv_change.egid;
ipc_set.sem_perm.mode = 0600;
semun.buf = &ipc_set;
for (i = 0; i < 3; i++) {
res = semctl (conn_info->semid, 0, IPC_SET, semun);
if (res == -1) {
return (-1);
}
}
return (0);
}
static void msg_send_or_queue (void *conn, const struct iovec *iov, unsigned int iov_len)
{
struct conn_info *conn_info = (struct conn_info *)conn;
unsigned int bytes_left;
unsigned int bytes_msg = 0;
int i;
struct outq_item *outq_item;
char *write_buf = 0;
/*
* Exit transmission if the connection is dead
*/
if (ipc_thread_active (conn) == 0) {
return;
}
bytes_left = shared_mem_dispatch_bytes_left (conn_info);
for (i = 0; i < iov_len; i++) {
bytes_msg += iov[i].iov_len;
}
if (bytes_left < bytes_msg || list_empty (&conn_info->outq_head) == 0) {
outq_item = api->malloc (sizeof (struct outq_item));
if (outq_item == NULL) {
ipc_disconnect (conn);
return;
}
outq_item->msg = api->malloc (bytes_msg);
if (outq_item->msg == 0) {
api->free (outq_item);
ipc_disconnect (conn);
return;
}
write_buf = outq_item->msg;
for (i = 0; i < iov_len; i++) {
memcpy (write_buf, iov[i].iov_base, iov[i].iov_len);
write_buf += iov[i].iov_len;
}
outq_item->mlen = bytes_msg;
list_init (&outq_item->list);
pthread_mutex_lock (&conn_info->mutex);
if (list_empty (&conn_info->outq_head)) {
conn_info->notify_flow_control_enabled = 1;
api->poll_dispatch_modify (conn_info->fd,
POLLIN|POLLOUT|POLLNVAL);
}
list_add_tail (&outq_item->list, &conn_info->outq_head);
pthread_mutex_unlock (&conn_info->mutex);
return;
}
msg_send (conn, iov, iov_len, MSG_SEND_LOCKED);
}
void coroipcs_refcount_inc (void *conn)
{
struct conn_info *conn_info = (struct conn_info *)conn;
pthread_mutex_lock (&conn_info->mutex);
conn_info->refcount++;
pthread_mutex_unlock (&conn_info->mutex);
}
void coroipcs_refcount_dec (void *conn)
{
struct conn_info *conn_info = (struct conn_info *)conn;
pthread_mutex_lock (&conn_info->mutex);
conn_info->refcount--;
pthread_mutex_unlock (&conn_info->mutex);
}
int coroipcs_dispatch_send (void *conn, const void *msg, size_t mlen)
{
struct iovec iov;
iov.iov_base = (void *)msg;
iov.iov_len = mlen;
msg_send_or_queue (conn, &iov, 1);
return (0);
}
int coroipcs_dispatch_iov_send (void *conn, const struct iovec *iov, unsigned int iov_len)
{
msg_send_or_queue (conn, iov, iov_len);
return (0);
}
int coroipcs_handler_accept (
int fd,
int revent,
void *data)
{
socklen_t addrlen;
struct sockaddr_un un_addr;
int new_fd;
#ifdef COROSYNC_LINUX
int on = 1;
#endif
int res;
addrlen = sizeof (struct sockaddr_un);
retry_accept:
new_fd = accept (fd, (struct sockaddr *)&un_addr, &addrlen);
if (new_fd == -1 && errno == EINTR) {
goto retry_accept;
}
if (new_fd == -1) {
api->log_printf ("Could not accept Library connection: %s\n", strerror (errno));
return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
}
res = fcntl (new_fd, F_SETFL, O_NONBLOCK);
if (res == -1) {
api->log_printf ("Could not set non-blocking operation on library connection: %s\n", strerror (errno));
close (new_fd);
return (0); /* This is an error, but -1 would indicate disconnect from poll loop */
}
/*
* Valid accept
*/
/*
* Request credentials of sender provided by kernel
*/
#ifdef COROSYNC_LINUX
setsockopt(new_fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
#endif
res = conn_info_create (new_fd);
if (res != 0) {
close (new_fd);
}
return (0);
}
int coroipcs_handler_dispatch (
int fd,
int revent,
void *context)
{
mar_req_setup_t *req_setup;
struct conn_info *conn_info = (struct conn_info *)context;
int res;
char buf;
if (ipc_thread_exiting (conn_info)) {
return conn_info_destroy (conn_info);
}
/*
* If an error occurs, request exit
*/
if (revent & (POLLERR|POLLHUP)) {
ipc_disconnect (conn_info);
return (0);
}
/*
* Read the header and process it
*/
if (conn_info->service == SOCKET_SERVICE_INIT && (revent & POLLIN)) {
/*
* Receive in a nonblocking fashion the request
* IF security invalid, send TRY_AGAIN, otherwise
* send OK
*/
res = req_setup_recv (conn_info);
if (res == -1) {
req_setup_send (conn_info, CS_ERR_TRY_AGAIN);
}
if (res != 1) {
return (0);
}
req_setup_send (conn_info, CS_OK);
pthread_mutex_init (&conn_info->mutex, NULL);
req_setup = (mar_req_setup_t *)conn_info->setup_msg;
/*
* Is the service registered ?
*/
if (api->service_available (req_setup->service) == 0) {
ipc_disconnect (conn_info);
return (0);
}
conn_info->semkey = req_setup->semkey;
res = memory_map (
req_setup->control_file,
req_setup->control_size,
(void *)&conn_info->control_buffer);
conn_info->control_size = req_setup->control_size;
res = memory_map (
req_setup->request_file,
req_setup->request_size,
(void *)&conn_info->request_buffer);
conn_info->request_size = req_setup->request_size;
res = memory_map (
req_setup->response_file,
req_setup->response_size,
(void *)&conn_info->response_buffer);
conn_info->response_size = req_setup->response_size;
res = circular_memory_map (
req_setup->dispatch_file,
req_setup->dispatch_size,
(void *)&conn_info->dispatch_buffer);
conn_info->dispatch_size = req_setup->dispatch_size;
conn_info->service = req_setup->service;
conn_info->refcount = 0;
conn_info->notify_flow_control_enabled = 0;
conn_info->setup_bytes_read = 0;
conn_info->semid = semget (conn_info->semkey, 3, 0600);
conn_info->pending_semops = 0;
/*
* ipc thread is the only reference at startup
*/
- conn_info->refcount = 1;
+ conn_info->refcount = 1;
conn_info->state = CONN_STATE_THREAD_ACTIVE;
conn_info->private_data = api->malloc (api->private_data_size_get (conn_info->service));
memset (conn_info->private_data, 0,
api->private_data_size_get (conn_info->service));
api->init_fn_get (conn_info->service) (conn_info);
pthread_attr_init (&conn_info->thread_attr);
/*
* IA64 needs more stack space then other arches
*/
#if defined(__ia64__)
pthread_attr_setstacksize (&conn_info->thread_attr, 400000);
#else
pthread_attr_setstacksize (&conn_info->thread_attr, 200000);
#endif
pthread_attr_setdetachstate (&conn_info->thread_attr, PTHREAD_CREATE_JOINABLE);
res = pthread_create (&conn_info->thread,
&conn_info->thread_attr,
pthread_ipc_consumer,
conn_info);
/*
* Security check - disallow multiple configurations of
* the ipc connection
*/
if (conn_info->service == SOCKET_SERVICE_INIT) {
conn_info->service = -1;
}
} else
if (revent & POLLIN) {
coroipcs_refcount_inc (conn_info);
res = recv (fd, &buf, 1, MSG_NOSIGNAL);
if (res == 1) {
switch (buf) {
case MESSAGE_REQ_OUTQ_FLUSH:
outq_flush (conn_info);
break;
case MESSAGE_REQ_CHANGE_EUID:
if (priv_change (conn_info) == -1) {
ipc_disconnect (conn_info);
}
break;
default:
res = 0;
break;
}
coroipcs_refcount_dec (conn_info);
}
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
/* On many OS poll never return POLLHUP or POLLERR.
* EOF is detected when recvmsg return 0.
*/
if (res == 0) {
ipc_disconnect (conn_info);
return (0);
}
#endif
}
coroipcs_refcount_inc (conn_info);
pthread_mutex_lock (&conn_info->mutex);
if ((conn_info->state == CONN_STATE_THREAD_ACTIVE) && (revent & POLLOUT)) {
buf = !list_empty (&conn_info->outq_head);
for (; conn_info->pending_semops;) {
res = send (conn_info->fd, &buf, 1, MSG_NOSIGNAL);
if (res == 1) {
conn_info->pending_semops--;
} else {
break;
}
}
if (conn_info->notify_flow_control_enabled) {
buf = 2;
res = send (conn_info->fd, &buf, 1, MSG_NOSIGNAL);
if (res == 1) {
conn_info->notify_flow_control_enabled = 0;
}
}
if (conn_info->notify_flow_control_enabled == 0 &&
conn_info->pending_semops == 0) {
api->poll_dispatch_modify (conn_info->fd,
POLLIN|POLLNVAL);
}
}
pthread_mutex_unlock (&conn_info->mutex);
coroipcs_refcount_dec (conn_info);
return (0);
}
diff --git a/exec/coropoll.c b/exec/coropoll.c
index fc94faca..50a3a2d8 100644
--- a/exec/coropoll.c
+++ b/exec/coropoll.c
@@ -1,438 +1,438 @@
/*
* Copyright (c) 2003-2004 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <errno.h>
#include <pthread.h>
#include <sys/poll.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <corosync/hdb.h>
#include <corosync/totem/coropoll.h>
#include <corosync/list.h>
#include "tlist.h"
typedef int (*dispatch_fn_t) (hdb_handle_t hdb_handle_t, int fd, int revents, void *data);
struct poll_entry {
struct pollfd ufd;
dispatch_fn_t dispatch_fn;
void *data;
};
struct poll_instance {
struct poll_entry *poll_entries;
struct pollfd *ufds;
int poll_entry_count;
struct timerlist timerlist;
int stop_requested;
};
DECLARE_HDB_DATABASE (poll_instance_database);
hdb_handle_t poll_create (void)
{
hdb_handle_t handle;
struct poll_instance *poll_instance;
unsigned int res;
res = hdb_handle_create (&poll_instance_database,
sizeof (struct poll_instance), &handle);
if (res != 0) {
goto error_exit;
}
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
goto error_destroy;
}
-
+
poll_instance->poll_entries = 0;
poll_instance->ufds = 0;
poll_instance->poll_entry_count = 0;
poll_instance->stop_requested = 0;
timerlist_init (&poll_instance->timerlist);
return (handle);
error_destroy:
hdb_handle_destroy (&poll_instance_database, handle);
-
+
error_exit:
return (-1);
}
int poll_destroy (hdb_handle_t handle)
{
struct poll_instance *poll_instance;
int res = 0;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
free (poll_instance->poll_entries);
free (poll_instance->ufds);
hdb_handle_destroy (&poll_instance_database, handle);
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_dispatch_add (
hdb_handle_t handle,
int fd,
int events,
void *data,
int (*dispatch_fn) (
hdb_handle_t hdb_handle_t,
int fd,
int revents,
void *data))
{
struct poll_instance *poll_instance;
struct poll_entry *poll_entries;
struct pollfd *ufds;
int found = 0;
int install_pos;
int res = 0;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
for (found = 0, install_pos = 0; install_pos < poll_instance->poll_entry_count; install_pos++) {
if (poll_instance->poll_entries[install_pos].ufd.fd == -1) {
found = 1;
break;
}
}
if (found == 0) {
/*
* Grow pollfd list
*/
poll_entries = (struct poll_entry *)realloc (poll_instance->poll_entries,
(poll_instance->poll_entry_count + 1) *
sizeof (struct poll_entry));
if (poll_entries == NULL) {
res = -ENOMEM;
goto error_put;
}
poll_instance->poll_entries = poll_entries;
-
+
ufds = (struct pollfd *)realloc (poll_instance->ufds,
(poll_instance->poll_entry_count + 1) *
sizeof (struct pollfd));
if (ufds == NULL) {
res = -ENOMEM;
goto error_put;
}
poll_instance->ufds = ufds;
poll_instance->poll_entry_count += 1;
install_pos = poll_instance->poll_entry_count - 1;
}
-
+
/*
* Install new dispatch handler
*/
poll_instance->poll_entries[install_pos].ufd.fd = fd;
poll_instance->poll_entries[install_pos].ufd.events = events;
poll_instance->poll_entries[install_pos].ufd.revents = 0;
poll_instance->poll_entries[install_pos].dispatch_fn = dispatch_fn;
poll_instance->poll_entries[install_pos].data = data;
error_put:
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_dispatch_modify (
hdb_handle_t handle,
int fd,
int events,
int (*dispatch_fn) (
hdb_handle_t hdb_handle_t,
int fd,
int revents,
void *data))
{
struct poll_instance *poll_instance;
int i;
int res = 0;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
/*
* Find file descriptor to modify events and dispatch function
*/
for (i = 0; i < poll_instance->poll_entry_count; i++) {
if (poll_instance->poll_entries[i].ufd.fd == fd) {
poll_instance->poll_entries[i].ufd.events = events;
poll_instance->poll_entries[i].dispatch_fn = dispatch_fn;
-
+
goto error_put;
}
}
res = -EBADF;
error_put:
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_dispatch_delete (
hdb_handle_t handle,
int fd)
{
struct poll_instance *poll_instance;
int i;
int res = 0;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
/*
* Find dispatch fd to delete
*/
res = -EBADF;
for (i = 0; i < poll_instance->poll_entry_count; i++) {
if (poll_instance->poll_entries[i].ufd.fd == fd) {
poll_instance->poll_entries[i].ufd.fd = -1;
poll_instance->poll_entries[i].ufd.revents = 0;
break;
}
}
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_timer_add (
hdb_handle_t handle,
int msec_duration, void *data,
void (*timer_fn) (void *data),
poll_timer_handle *timer_handle_out)
{
struct poll_instance *poll_instance;
int res = 0;
if (timer_handle_out == NULL) {
res = -ENOENT;
goto error_exit;
}
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
timerlist_add_duration (&poll_instance->timerlist,
timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out);
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_timer_delete (
hdb_handle_t handle,
poll_timer_handle th)
{
struct poll_instance *poll_instance;
int res = 0;
if (th == 0) {
return (0);
}
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
timerlist_del (&poll_instance->timerlist, (void *)th);
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_stop (
hdb_handle_t handle)
{
struct poll_instance *poll_instance;
unsigned int res;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
goto error_exit;
}
-
+
poll_instance->stop_requested = 1;
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (res);
}
int poll_run (
hdb_handle_t handle)
{
struct poll_instance *poll_instance;
int i;
unsigned long long expire_timeout_msec = -1;
int res;
int poll_entry_count;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
goto error_exit;
}
for (;;) {
for (i = 0; i < poll_instance->poll_entry_count; i++) {
memcpy (&poll_instance->ufds[i],
&poll_instance->poll_entries[i].ufd,
sizeof (struct pollfd));
}
expire_timeout_msec = timerlist_msec_duration_to_expire (&poll_instance->timerlist);
if (expire_timeout_msec != -1 && expire_timeout_msec > 0xFFFFFFFF) {
expire_timeout_msec = 0xFFFFFFFE;
}
retry_poll:
res = poll (poll_instance->ufds,
poll_instance->poll_entry_count, expire_timeout_msec);
if (poll_instance->stop_requested) {
return (0);
}
if (errno == EINTR && res == -1) {
goto retry_poll;
} else
if (res == -1) {
goto error_exit;
}
poll_entry_count = poll_instance->poll_entry_count;
for (i = 0; i < poll_entry_count; i++) {
if (poll_instance->ufds[i].fd != -1 &&
poll_instance->ufds[i].revents) {
res = poll_instance->poll_entries[i].dispatch_fn (handle,
- poll_instance->ufds[i].fd,
+ poll_instance->ufds[i].fd,
poll_instance->ufds[i].revents,
poll_instance->poll_entries[i].data);
/*
* Remove dispatch functions that return -1
*/
if (res == -1) {
poll_instance->poll_entries[i].ufd.fd = -1; /* empty entry */
}
}
}
timerlist_expire (&poll_instance->timerlist);
} /* for (;;) */
hdb_handle_put (&poll_instance_database, handle);
error_exit:
return (-1);
}
#ifdef COMPILE_OUT
void poll_print_state (
hdb_handle_t handle,
int fd)
{
struct poll_instance *poll_instance;
int i;
int res = 0;
res = hdb_handle_get (&poll_instance_database, handle,
(void *)&poll_instance);
if (res != 0) {
res = -ENOENT;
exit (1);
}
for (i = 0; i < poll_instance->poll_entry_count; i++) {
if (poll_instance->poll_entries[i].ufd.fd == fd) {
printf ("fd %d\n", poll_instance->poll_entries[i].ufd.fd);
printf ("events %d\n", poll_instance->poll_entries[i].ufd.events);
printf ("dispatch_fn %p\n", poll_instance->poll_entries[i].dispatch_fn);
}
}
}
-
+
#endif
diff --git a/exec/crypto.c b/exec/crypto.c
index 61c8164d..a66a1c7d 100644
--- a/exec/crypto.c
+++ b/exec/crypto.c
@@ -1,1346 +1,1346 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.com
*/
#include <config.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#if defined(COROSYNC_BSD)
#include <sys/endian.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include "crypto.h"
#define CONST64(n) n ## ULL
typedef uint32_t ulong32;
typedef uint64_t ulong64;
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ENDIAN_LITTLE
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ENDIAN_BIG
#elif _BYTE_ORDER == _LITTLE_ENDIAN
#define ENDIAN_LITTLE
#elif _BYTE_ORDER == _BIG_ENDIAN
#define ENDIAN_BIG
#else
#error "cannot detect byte order"
#endif
#if defined(COROSYNC_LINUX)
#if __WORDSIZE == 64
#define ENDIAN_64BITWORD
#endif
#if __WORDSIZE == 32
#define ENDIAN_32BITWORD
#endif
#else
/* XXX need to find a better default
*/
#define ENDIAN_32BITWORD
#endif
/* ---- HELPER MACROS ---- */
#ifdef ENDIAN_NEUTRAL
#define STORE32L(x, y) \
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
((unsigned long)((y)[2] & 255)<<16) | \
((unsigned long)((y)[1] & 255)<<8) | \
((unsigned long)((y)[0] & 255)); }
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
#endif /* ENDIAN_NEUTRAL */
#ifdef ENDIAN_LITTLE
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
-#ifdef ENDIAN_32BITWORD
+#ifdef ENDIAN_32BITWORD
#define STORE32L(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32L(x, y) \
memcpy(&(x), y, 4);
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#else /* 64-bit words then */
#define STORE32L(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32L(x, y) \
{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
#define STORE64L(x, y) \
{ ulong64 __t = (x); memcpy(y, &__t, 8); }
#define LOAD64L(x, y) \
{ memcpy(&(x), y, 8); }
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_LITTLE */
#ifdef ENDIAN_BIG
#define STORE32L(x, y) \
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
((unsigned long)((y)[2] & 255)<<16) | \
((unsigned long)((y)[1] & 255)<<8) | \
((unsigned long)((y)[0] & 255)); }
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
-#ifdef ENDIAN_32BITWORD
+#ifdef ENDIAN_32BITWORD
#define STORE32H(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32H(x, y) \
memcpy(&(x), y, 4);
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
(((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
#else /* 64-bit words then */
#define STORE32H(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32H(x, y) \
{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
#define STORE64H(x, y) \
{ ulong64 __t = (x); memcpy(y, &__t, 8); }
#define LOAD64H(x, y) \
{ memcpy(&(x), y, 8); }
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_BIG */
#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
#if defined(__GNUC__) && defined(__i386__) && !defined(INTEL_CC)
static inline unsigned long ROL(unsigned long word, int i)
{
__asm__("roll %%cl,%0"
:"=r" (word)
:"0" (word),"c" (i));
return word;
}
static inline unsigned long ROR(unsigned long word, int i)
{
__asm__("rorl %%cl,%0"
:"=r" (word)
:"0" (word),"c" (i));
return word;
}
#else
/* rotates the hard way */
#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#endif
#define ROL64(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
#undef MAX
#undef MIN
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
/* extract a byte portably */
#define byte(x, n) (((x) >> (8 * (n))) & 255)
#define CONST64(n) n ## ULL
/* a simple macro for making hash "process" functions */
#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
int func_name (hash_state * md, const unsigned char *buf, unsigned long len) \
{ \
unsigned long n; \
if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
return CRYPT_INVALID_ARG; \
} \
while (len > 0) { \
if (md-> state_var .curlen == 0 && len >= block_size) { \
compress_name (md, (unsigned char *)buf); \
md-> state_var .length += block_size * 8; \
buf += block_size; \
len -= block_size; \
} else { \
n = MIN(len, (block_size - md-> state_var .curlen)); \
memcpy(md-> state_var .buf + md-> state_var.curlen, buf, (size_t)n); \
md-> state_var .curlen += n; \
buf += n; \
len -= n; \
if (md-> state_var .curlen == block_size) { \
compress_name (md, md-> state_var .buf); \
md-> state_var .length += 8*block_size; \
md-> state_var .curlen = 0; \
} \
} \
} \
return CRYPT_OK; \
}
#define MAXBLOCKSIZE 128
/*
* The mycrypt_macros.h file
*/
/* ---- HELPER MACROS ---- */
#ifdef ENDIAN_NEUTRAL
#define STORE32L(x, y) \
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
((unsigned long)((y)[2] & 255)<<16) | \
((unsigned long)((y)[1] & 255)<<8) | \
((unsigned long)((y)[0] & 255)); }
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
#endif /* ENDIAN_NEUTRAL */
#ifdef ENDIAN_LITTLE
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
-#ifdef ENDIAN_32BITWORD
+#ifdef ENDIAN_32BITWORD
#define STORE32L(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32L(x, y) \
memcpy(&(x), y, 4);
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#else /* 64-bit words then */
#define STORE32L(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32L(x, y) \
{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
#define STORE64L(x, y) \
{ ulong64 __t = (x); memcpy(y, &__t, 8); }
#define LOAD64L(x, y) \
{ memcpy(&(x), y, 8); }
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_LITTLE */
#ifdef ENDIAN_BIG
#define STORE32L(x, y) \
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
((unsigned long)((y)[2] & 255)<<16) | \
((unsigned long)((y)[1] & 255)<<8) | \
((unsigned long)((y)[0] & 255)); }
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
-#ifdef ENDIAN_32BITWORD
+#ifdef ENDIAN_32BITWORD
#define STORE32H(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32H(x, y) \
memcpy(&(x), y, 4);
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \
(((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); }
#else /* 64-bit words then */
#define STORE32H(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD32H(x, y) \
{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
#define STORE64H(x, y) \
{ ulong64 __t = (x); memcpy(y, &__t, 8); }
#define LOAD64H(x, y) \
{ memcpy(&(x), y, 8); }
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_BIG */
#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
#define ROL64(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
#undef MAX
#undef MIN
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
/* extract a byte portably */
#define byte(x, n) (((x) >> (8 * (n))) & 255)
/* $Id: s128multab.h 213 2003-12-16 04:27:12Z ggr $ */
/* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */
/* Multiplication table for Turing using 0xD02B4367 */
static const ulong32 Multab[256] = {
0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9,
0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478,
0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697,
0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A,
0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5,
0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04,
0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613,
0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D,
0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51,
0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80,
0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F,
0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F,
0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90,
0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41,
0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D,
0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703,
0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14,
0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5,
0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A,
0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787,
0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568,
0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9,
0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699,
0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7,
0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB,
0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A,
0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5,
0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523,
0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC,
0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D,
0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61,
0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F,
0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E,
0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F,
0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0,
0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D,
0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2,
0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433,
0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24,
0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A,
0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566,
0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7,
0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658,
};
/* $Id: s128sbox.h 213 2003-12-16 04:27:12Z ggr $ */
/* Sbox for SOBER-128 */
/*
* This is really the combination of two SBoxes; the least significant
* 24 bits comes from:
* 8->32 Sbox generated by Millan et. al. at Queensland University of
* Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter,
* "On the Design of 8*32 S-boxes". Unpublished report, by the
* Information Systems Research Centre,
* Queensland University of Technology, 1999.
- *
+ *
* The most significant 8 bits are the Skipjack "F table", which can be
* found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf .
* In this optimised table, though, the intent is to XOR the word from
* the table selected by the high byte with the input word. Thus, the
* high byte is actually the Skipjack F-table entry XORED with its
* table index.
*/
static const ulong32 Sbox[256] = {
0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4,
0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae,
0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c,
0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35,
0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e,
0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b,
0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f,
0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1,
0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd,
0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3,
0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f,
0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36,
0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf,
0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816,
0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d,
0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af,
0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6,
0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418,
0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0,
0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd,
0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088,
0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759,
0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895,
0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66,
0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc,
0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1,
0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911,
0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e,
0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515,
0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133,
0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226,
0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084,
0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb,
0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184,
0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420,
0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02,
0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655,
0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c,
0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418,
0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473,
0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a,
0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0,
0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21,
0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36,
0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5,
0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6,
0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0,
0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795,
0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0,
0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78,
0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da,
0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a,
0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118,
0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed,
0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd,
0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b,
0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921,
0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e,
0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5,
0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8,
0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376,
0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a,
0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8,
0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40,
};
/* Implementation of SOBER-128 by Tom St Denis.
* Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
*/
-const struct _prng_descriptor sober128_desc =
+const struct _prng_descriptor sober128_desc =
{
"sober128", 64,
&sober128_start,
&sober128_add_entropy,
&sober128_ready,
&sober128_read,
};
const struct _prng_descriptor *prng_descriptor[] = {
&sober128_desc
};
/* don't change these... */
#define N 17
#define FOLD N /* how many iterations of folding to do */
#define INITKONST 0x6996c53a /* value of KONST to use during key loading */
#define KEYP 15 /* where to insert key words */
#define FOLDP 4 /* where to insert non-linear feedback */
#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF))
static ulong32 BYTE2WORD(const unsigned char *b)
{
ulong32 t;
LOAD32L(t, b);
return t;
}
#define WORD2BYTE(w, b) STORE32L(b, w)
static void XORWORD(ulong32 w, unsigned char *b)
{
ulong32 t;
LOAD32L(t, b);
t ^= w;
STORE32L(t, b);
}
/* give correct offset for the current position of the register,
* where logically R[0] is at position "zero".
*/
#define OFF(zero, i) (((zero)+(i)) % N)
/* step the LFSR */
/* After stepping, "zero" moves right one place */
#define STEP(R,z) \
R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
static void cycle(ulong32 *R)
{
ulong32 t;
int i;
STEP(R,0);
t = R[0];
for (i = 1; i < N; ++i) {
R[i-1] = R[i];
}
R[N-1] = t;
}
/* Return a non-linear function of some parts of the register.
*/
#define NLFUNC(c,z) \
{ \
t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
t ^= Sbox[(t >> 24) & 0xFF]; \
t = ROR(t, 8); \
t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
t ^= Sbox[(t >> 24) & 0xFF]; \
t = t + c->R[OFF(z,13)]; \
}
static ulong32 nltap(struct sober128_prng *c)
{
ulong32 t;
NLFUNC(c, 0);
return t;
}
/* initialise to known state
*/
int sober128_start(prng_state *prng)
{
int i;
struct sober128_prng *c;
c = &(prng->sober128);
-
+
/* Register initialised to Fibonacci numbers */
c->R[0] = 1;
c->R[1] = 1;
for (i = 2; i < N; ++i) {
c->R[i] = c->R[i-1] + c->R[i-2];
}
c->konst = INITKONST;
/* next add_entropy will be the key */
c->flag = 1;
c->set = 0;
return CRYPT_OK;
}
/* Save the current register state
*/
static void s128_savestate(struct sober128_prng *c)
{
int i;
for (i = 0; i < N; ++i) {
c->initR[i] = c->R[i];
}
}
/* initialise to previously saved register state
*/
static void s128_reloadstate(struct sober128_prng *c)
{
int i;
for (i = 0; i < N; ++i) {
c->R[i] = c->initR[i];
}
}
/* Initialise "konst"
*/
static void s128_genkonst(struct sober128_prng *c)
{
ulong32 newkonst;
do {
cycle(c->R);
newkonst = nltap(c);
} while ((newkonst & 0xFF000000) == 0);
c->konst = newkonst;
}
/* Load key material into the register
*/
#define ADDKEY(k) \
c->R[KEYP] += (k);
#define XORNL(nl) \
c->R[FOLDP] ^= (nl);
/* nonlinear diffusion of register for key */
-#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
+#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
static void s128_diffuse(struct sober128_prng *c)
{
ulong32 t;
/* relies on FOLD == N == 17! */
DROUND(0);
DROUND(1);
DROUND(2);
DROUND(3);
DROUND(4);
DROUND(5);
DROUND(6);
DROUND(7);
DROUND(8);
DROUND(9);
DROUND(10);
DROUND(11);
DROUND(12);
DROUND(13);
DROUND(14);
DROUND(15);
DROUND(16);
}
int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
{
struct sober128_prng *c;
ulong32 i, k;
c = &(prng->sober128);
if (c->flag == 1) {
/* this is the first call to the add_entropy so this input is the key */
/* len must be multiple of 4 bytes */
assert ((len & 3) == 0);
-
+
for (i = 0; i < len; i += 4) {
k = BYTE2WORD(&buf[i]);
ADDKEY(k);
cycle(c->R);
XORNL(nltap(c));
}
/* also fold in the length of the key */
ADDKEY(len);
/* now diffuse */
s128_diffuse(c);
s128_genkonst(c);
s128_savestate(c);
c->nbuf = 0;
- c->flag = 0;
+ c->flag = 0;
c->set = 1;
} else {
/* ok we are adding an IV then... */
s128_reloadstate(c);
/* len must be multiple of 4 bytes */
assert ((len & 3) == 0);
-
+
for (i = 0; i < len; i += 4) {
k = BYTE2WORD(&buf[i]);
ADDKEY(k);
cycle(c->R);
XORNL(nltap(c));
}
/* also fold in the length of the key */
ADDKEY(len);
/* now diffuse */
s128_diffuse(c);
c->nbuf = 0;
}
return CRYPT_OK;
}
int sober128_ready(prng_state *prng)
{
return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR;
}
/* XOR pseudo-random bytes into buffer
*/
#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, buf+(z*4));
unsigned long sober128_read(unsigned char *buf, unsigned long nbytes, prng_state *prng)
{
struct sober128_prng *c;
ulong32 t, tlen;
c = &(prng->sober128);
t = 0;
tlen = nbytes;
-
+
/* handle any previously buffered bytes */
while (c->nbuf != 0 && nbytes != 0) {
*buf++ ^= c->sbuf & 0xFF;
c->sbuf >>= 8;
c->nbuf -= 8;
--nbytes;
}
#ifndef SMALL_CODE
/* do lots at a time, if there's enough to do */
while (nbytes >= N*4) {
SROUND(0);
SROUND(1);
SROUND(2);
SROUND(3);
SROUND(4);
SROUND(5);
SROUND(6);
SROUND(7);
SROUND(8);
SROUND(9);
SROUND(10);
SROUND(11);
SROUND(12);
SROUND(13);
SROUND(14);
SROUND(15);
SROUND(16);
buf += 4*N;
nbytes -= 4*N;
}
#endif
/* do small or odd size buffers the slow way */
while (4 <= nbytes) {
cycle(c->R);
t = nltap(c);
XORWORD(t, buf);
buf += 4;
nbytes -= 4;
}
/* handle any trailing bytes */
if (nbytes != 0) {
cycle(c->R);
c->sbuf = nltap(c);
c->nbuf = 32;
while (c->nbuf != 0 && nbytes != 0) {
*buf++ ^= c->sbuf & 0xFF;
c->sbuf >>= 8;
c->nbuf -= 8;
--nbytes;
}
}
return tlen;
}
/* SHA1 code by Tom St Denis */
const struct _hash_descriptor sha1_desc =
{
"sha1",
2,
20,
64,
/* DER identifier */
- { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E,
+ { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E,
0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14 },
15,
&sha1_init,
&sha1_process,
&sha1_done,
};
#define F0(x,y,z) (z ^ (x & (y ^ z)))
#define F1(x,y,z) (x ^ y ^ z)
#define F2(x,y,z) ((x & y) | (z & (x | y)))
#define F3(x,y,z) (x ^ y ^ z)
static void sha1_compress(hash_state *md, const unsigned char *buf)
{
ulong32 a,b,c,d,e,W[80],i;
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], buf + (4*i));
}
/* copy state */
a = md->sha1.state[0];
b = md->sha1.state[1];
c = md->sha1.state[2];
d = md->sha1.state[3];
e = md->sha1.state[4];
/* expand it */
for (i = 16; i < 80; i++) {
- W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
+ W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
}
/* compress */
/* round one */
#define FF0(a,b,c,d,e,i) e = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROL(b, 30);
#define FF1(a,b,c,d,e,i) e = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROL(b, 30);
#define FF2(a,b,c,d,e,i) e = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROL(b, 30);
#define FF3(a,b,c,d,e,i) e = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROL(b, 30);
-
+
for (i = 0; i < 20; ) {
FF0(a,b,c,d,e,i++);
FF0(e,a,b,c,d,i++);
FF0(d,e,a,b,c,i++);
FF0(c,d,e,a,b,i++);
FF0(b,c,d,e,a,i++);
}
/* round two */
- for (; i < 40; ) {
+ for (; i < 40; ) {
FF1(a,b,c,d,e,i++);
FF1(e,a,b,c,d,i++);
FF1(d,e,a,b,c,i++);
FF1(c,d,e,a,b,i++);
FF1(b,c,d,e,a,i++);
}
/* round three */
- for (; i < 60; ) {
+ for (; i < 60; ) {
FF2(a,b,c,d,e,i++);
FF2(e,a,b,c,d,i++);
FF2(d,e,a,b,c,i++);
FF2(c,d,e,a,b,i++);
FF2(b,c,d,e,a,i++);
}
/* round four */
- for (; i < 80; ) {
+ for (; i < 80; ) {
FF3(a,b,c,d,e,i++);
FF3(e,a,b,c,d,i++);
FF3(d,e,a,b,c,i++);
FF3(c,d,e,a,b,i++);
FF3(b,c,d,e,a,i++);
}
#undef FF0
#undef FF1
#undef FF2
#undef FF3
/* store */
md->sha1.state[0] = md->sha1.state[0] + a;
md->sha1.state[1] = md->sha1.state[1] + b;
md->sha1.state[2] = md->sha1.state[2] + c;
md->sha1.state[3] = md->sha1.state[3] + d;
md->sha1.state[4] = md->sha1.state[4] + e;
}
void sha1_init(hash_state * md)
{
md->sha1.state[0] = 0x67452301UL;
md->sha1.state[1] = 0xefcdab89UL;
md->sha1.state[2] = 0x98badcfeUL;
md->sha1.state[3] = 0x10325476UL;
md->sha1.state[4] = 0xc3d2e1f0UL;
md->sha1.curlen = 0;
md->sha1.length = 0;
}
HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
int sha1_done(hash_state * md, unsigned char *hash)
{
int i;
/*
* Assert there isn't an invalid argument
*/
- assert (md->sha1.curlen < sizeof (md->sha1.buf));
+ assert (md->sha1.curlen < sizeof (md->sha1.buf));
/* increase the length of the message */
md->sha1.length += md->sha1.curlen * 8;
/* append the '1' bit */
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->sha1.curlen > 56) {
while (md->sha1.curlen < 64) {
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
}
sha1_compress(md, md->sha1.buf);
md->sha1.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->sha1.curlen < 56) {
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->sha1.length, md->sha1.buf+56);
sha1_compress(md, md->sha1.buf);
/* copy output */
for (i = 0; i < 5; i++) {
STORE32H(md->sha1.state[i], hash+(4*i));
}
return CRYPT_OK;
}
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
{
unsigned char buf[128];
unsigned long hashsize;
unsigned long i;
int err;
hmac->hash = hash;
hashsize = hash_descriptor[hash]->hashsize;
/* valid key length? */
assert (keylen > 0);
assert (keylen <= hash_descriptor[hash]->blocksize);
memcpy(hmac->key, key, (size_t)keylen);
if(keylen < hash_descriptor[hash]->blocksize) {
memset((hmac->key) + keylen, 0, (size_t)(hash_descriptor[hash]->blocksize - keylen));
}
// Create the initial vector for step (3)
for(i=0; i < hash_descriptor[hash]->blocksize; i++) {
buf[i] = hmac->key[i] ^ 0x36;
}
// Pre-pend that to the hash data
hash_descriptor[hash]->init(&hmac->md);
err = hash_descriptor[hash]->process(&hmac->md, buf, hash_descriptor[hash]->blocksize);
- return err;
+ return err;
}
int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
{
return hash_descriptor[hmac->hash]->process(&hmac->md, buf, len);
}
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
{
unsigned char buf[128];
unsigned char isha[256];
unsigned long hashsize, i;
int hash, err;
/* test hash */
hash = hmac->hash;
/* get the hash message digest size */
hashsize = hash_descriptor[hash]->hashsize;
// Get the hash of the first HMAC vector plus the data
if ((err = hash_descriptor[hash]->done(&hmac->md, isha)) != CRYPT_OK) {
goto __ERR;
}
// Create the second HMAC vector vector for step (3)
for(i=0; i < hash_descriptor[hash]->blocksize; i++) {
buf[i] = hmac->key[i] ^ 0x5C;
}
// Now calculate the "outer" hash for step (5), (6), and (7)
hash_descriptor[hash]->init(&hmac->md);
if ((err = hash_descriptor[hash]->process(&hmac->md, buf, hash_descriptor[hash]->blocksize)) != CRYPT_OK) {
goto __ERR;
}
if ((err = hash_descriptor[hash]->process(&hmac->md, isha, hashsize)) != CRYPT_OK) {
goto __ERR;
}
if ((err = hash_descriptor[hash]->done(&hmac->md, buf)) != CRYPT_OK) {
goto __ERR;
}
- // copy to output
+ // copy to output
for (i = 0; i < hashsize && i < *outlen; i++) {
hashOut[i] = buf[i];
}
*outlen = i;
err = CRYPT_OK;
__ERR:
return err;
}
const struct _hash_descriptor *hash_descriptor[] =
{
&sha1_desc
};
/* portable way to get secure random bits to feed a PRNG */
/* on *NIX read /dev/random */
-static unsigned long rng_nix(unsigned char *buf, unsigned long len,
+static unsigned long rng_nix(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
int fd;
unsigned long rb;
fd = open ("/dev/urandom", O_RDONLY);
-
+
rb = (unsigned long)read (fd, buf, len);
close (fd);
return (rb);
}
/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
#if defined(XCLOCKS_PER_SEC)
#define ANSI_RNG
-static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
+static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
clock_t t1;
int l, acc, bits, a, b;
if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
return 0;
}
l = len;
bits = 8;
acc = a = b = 0;
while (len--) {
if (callback != NULL) callback();
while (bits--) {
do {
t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
} while (a == b);
acc = (acc << 1) | a;
}
- *buf++ = acc;
+ *buf++ = acc;
acc = 0;
bits = 8;
}
acc = bits = a = b = 0;
return l;
}
-#endif
+#endif
-unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
+unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
unsigned long x;
x = rng_nix(buf, len, callback); if (x != 0) { return x; }
#ifdef ANSI_RNG
x = rng_ansic(buf, len, callback); if (x != 0) { return x; }
#endif
return 0;
}
-int rng_make_prng(int bits, int wprng, prng_state *prng,
+int rng_make_prng(int bits, int wprng, prng_state *prng,
void (*callback)(void))
{
unsigned char buf[256];
int err;
-
+
if (bits < 64 || bits > 1024) {
return CRYPT_INVALID_PRNGSIZE;
}
if ((err = prng_descriptor[wprng]->start(prng)) != CRYPT_OK) {
return err;
}
bits = ((bits/8)+((bits&7)!=0?1:0)) * 2;
if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) {
return CRYPT_ERROR_READPRNG;
}
if ((err = prng_descriptor[wprng]->add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) {
return err;
}
if ((err = prng_descriptor[wprng]->ready(prng)) != CRYPT_OK) {
return err;
}
return CRYPT_OK;
}
diff --git a/exec/crypto.h b/exec/crypto.h
index 427dc16a..a154ff76 100644
--- a/exec/crypto.h
+++ b/exec/crypto.h
@@ -1,134 +1,134 @@
#ifndef CRYPTO_H_DEFINED
#define CRYPTO_H_DEFINED
#include <stdint.h>
#define DIGEST_SHA1 0
#define PRNG_SOBER 0
enum {
CRYPT_OK=0, /* Result OK */
CRYPT_ERROR, /* Generic Error */
CRYPT_NOP, /* Not a failure but no operation was performed */
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
CRYPT_INVALID_PACKET, /* Invalid input packet given */
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
CRYPT_INVALID_HASH, /* Invalid hash specified */
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
CRYPT_MEM, /* Out of memory */
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
CRYPT_INVALID_ARG, /* Generic invalid argument */
CRYPT_FILE_NOTFOUND, /* File Not Found */
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
CRYPT_PK_DUP, /* Duplicate key already in key ring */
CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */
};
struct sha1_state {
unsigned long long length;
unsigned long state[5], curlen;
unsigned char buf[64];
};
typedef union Hash_state {
struct sha1_state sha1;
} hash_state;
struct _hash_descriptor {
const char *name;
unsigned char ID;
unsigned long hashsize; /* digest output size in bytes */
unsigned long blocksize; /* the block size the hash uses */
unsigned char DER[64]; /* DER encoded identifier */
unsigned long DERlen; /* length of DER encoding */
void (*init)(hash_state *);
int (*process)(hash_state *, const unsigned char *, unsigned long);
int (*done)(hash_state *, unsigned char *);
int (*test)(void);
};
extern const struct _hash_descriptor *hash_descriptor[];
void sha1_init(hash_state * md);
int sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
int sha1_done(hash_state * md, unsigned char *hash);
int sha1_test(void);
int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen);
#define MAXBLOCKSIZE 128
typedef struct Hmac_state {
hash_state md;
int hash;
hash_state hashstate;
unsigned char key[MAXBLOCKSIZE];
} hmac_state;
int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len);
int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen);
int hmac_test(void);
int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
- const unsigned char *data, unsigned long len,
+ const unsigned char *data, unsigned long len,
unsigned char *dst, unsigned long *dstlen);
struct sober128_prng {
uint32_t R[17], /* Working storage for the shift register */
- initR[17], /* saved register contents */
+ initR[17], /* saved register contents */
konst, /* key dependent constant */
sbuf; /* partial word encryption buffer */
int nbuf, /* number of part-word stream bits buffered */
flag, /* first add_entropy call or not? */
set; /* did we call add_entropy to set key? */
-
+
};
typedef union Prng_state {
struct sober128_prng sober128;
} prng_state;
struct _prng_descriptor {
const char *name;
int export_size; /* size in bytes of exported state */
int (*start)(prng_state *);
int (*add_entropy)(const unsigned char *, unsigned long, prng_state *);
int (*ready)(prng_state *);
unsigned long (*read)(unsigned char *, unsigned long, prng_state *);
};
extern const struct _prng_descriptor *prng_descriptor[];
int sober128_start(prng_state *prng);
int sober128_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
int sober128_ready(prng_state *prng);
unsigned long sober128_read(unsigned char *buf, unsigned long len, prng_state *prng);
int sober128_done(prng_state *prng);
int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng);
int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng);
int sober128_test(void);
-unsigned long rng_get_bytes(unsigned char *buf,
- unsigned long len,
+unsigned long rng_get_bytes(unsigned char *buf,
+ unsigned long len,
void (*callback)(void));
int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));
#endif /* CRYPTO_H_DEFINED */
diff --git a/exec/logsys.c b/exec/logsys.c
index 30b65986..613574d0 100644
--- a/exec/logsys.c
+++ b/exec/logsys.c
@@ -1,1473 +1,1473 @@
/*
* Copyright (c) 2002-2004 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* Author: Steven Dake (sdake@redhat.com)
* Author: Lon Hohberger (lhh@redhat.com)
* Author: Fabio M. Di Nitto (fdinitto@redhat.com)
*
* All rights reserved.
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#if defined(COROSYNC_LINUX)
#include <linux/un.h>
#endif
#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
#include <sys/un.h>
#endif
#define SYSLOG_NAMES
#include <syslog.h>
#include <stdlib.h>
#include <pthread.h>
#include <corosync/engine/logsys.h>
/*
* similar to syslog facilities/priorities tables,
* make a tag table for internal use
*/
#ifdef SYSLOG_NAMES
struct syslog_names {
const char *c_name;
int c_val;
};
struct syslog_names tagnames[] =
{
{ "log", LOGSYS_TAG_LOG },
{ "enter", LOGSYS_TAG_ENTER },
{ "leave", LOGSYS_TAG_LEAVE },
{ "trace1", LOGSYS_TAG_TRACE1 },
{ "trace2", LOGSYS_TAG_TRACE2 },
{ "trace3", LOGSYS_TAG_TRACE3 },
{ "trace4", LOGSYS_TAG_TRACE4 },
{ "trace5", LOGSYS_TAG_TRACE5 },
{ "trace6", LOGSYS_TAG_TRACE6 },
{ "trace7", LOGSYS_TAG_TRACE7 },
{ "trace8", LOGSYS_TAG_TRACE8 },
{ NULL, -1 }
};
#endif
/*
* These are not static so they can be read from the core file
*/
int *flt_data;
int flt_data_size;
#define COMBINE_BUFFER_SIZE 2048
/* values for logsys_logger init_status */
#define LOGSYS_LOGGER_INIT_DONE 0
#define LOGSYS_LOGGER_NEEDS_INIT 1
static int logsys_system_needs_init = LOGSYS_LOGGER_NEEDS_INIT;
/*
* need unlogical order to preserve 64bit alignment
*/
struct logsys_logger {
char subsys[LOGSYS_MAX_SUBSYS_NAMELEN]; /* subsystem name */
char *logfile; /* log to file */
FILE *logfile_fp; /* track file descriptor */
unsigned int mode; /* subsystem mode */
unsigned int debug; /* debug on|off */
unsigned int tags; /* trace tags */
int syslog_facility; /* facility */
int syslog_priority; /* priority */
int logfile_priority; /* priority to file */
int init_status; /* internal field to handle init queues
for subsystems */
};
/*
* operating global variables
*/
static struct logsys_logger logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT + 1];
static int wthread_active = 0;
static int wthread_should_exit = 0;
static pthread_mutex_t logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned int records_written = 1;
static pthread_t logsys_thread_id;
static pthread_cond_t logsys_cond;
static pthread_mutex_t logsys_cond_mutex;
#if defined(HAVE_PTHREAD_SPIN_LOCK)
static pthread_spinlock_t logsys_idx_spinlock;
#else
static pthread_mutex_t logsys_idx_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static unsigned int log_rec_idx;
static int logsys_buffer_full = 0;
static char *format_buffer=NULL;
static int log_requests_pending = 0;
static int log_requests_lost = 0;
void *logsys_rec_end;
#define FDHEAD_INDEX (flt_data_size)
#define FDTAIL_INDEX (flt_data_size + 1)
/* forward declarations */
static void logsys_close_logfile(int subsysid);
/*
* Helpers for _logsys_log_rec functionality
*/
static inline void my_memcpy_32bit (int *dest, const int *src, unsigned int words)
{
unsigned int word_idx;
for (word_idx = 0; word_idx < words; word_idx++) {
dest[word_idx] = src[word_idx];
}
}
static inline void my_memcpy_8bit (char *dest, const char *src,
unsigned int bytes)
{
unsigned int byte_idx;
for (byte_idx = 0; byte_idx < bytes; byte_idx++) {
dest[byte_idx] = src[byte_idx];
}
}
#if defined(HAVE_PTHREAD_SPIN_LOCK)
static void logsys_lock (void)
{
pthread_spin_lock (&logsys_idx_spinlock);
}
static void logsys_unlock (void)
{
pthread_spin_unlock (&logsys_idx_spinlock);
}
#else
static void logsys_lock (void)
{
pthread_mutex_lock (&logsys_idx_mutex);
}
static void logsys_unlock (void)
{
pthread_mutex_unlock (&logsys_idx_mutex);
}
#endif
/*
* Before any write operation, a reclaim on the buffer area must be executed
*/
static inline void records_reclaim (unsigned int idx, unsigned int words)
{
unsigned int should_reclaim;
should_reclaim = 0;
if ((idx + words) >= flt_data_size) {
logsys_buffer_full = 1;
}
if (logsys_buffer_full == 0) {
return;
}
logsys_lock();
if (flt_data[FDTAIL_INDEX] > flt_data[FDHEAD_INDEX]) {
if (idx + words >= flt_data[FDTAIL_INDEX]) {
should_reclaim = 1;
}
} else {
if ((idx + words) >= (flt_data[FDTAIL_INDEX] + flt_data_size)) {
should_reclaim = 1;
}
}
if (should_reclaim) {
int words_needed = 0;
words_needed = words + 1;
do {
unsigned int old_tail;
words_needed -= flt_data[flt_data[FDTAIL_INDEX]];
old_tail = flt_data[FDTAIL_INDEX];
- flt_data[FDTAIL_INDEX] =
- (flt_data[FDTAIL_INDEX] +
+ flt_data[FDTAIL_INDEX] =
+ (flt_data[FDTAIL_INDEX] +
flt_data[flt_data[FDTAIL_INDEX]]) % (flt_data_size);
if (log_rec_idx == old_tail) {
log_requests_lost += 1;
log_rec_idx = flt_data[FDTAIL_INDEX];
}
} while (words_needed > 0);
}
logsys_unlock();
}
#define idx_word_step(idx) \
do { \
if (idx > (flt_data_size - 1)) { \
idx = 0; \
} \
} while (0);
#define idx_buffer_step(idx) \
do { \
if (idx > (flt_data_size - 1)) { \
idx = ((idx) % (flt_data_size)); \
} \
} while (0);
/*
* Internal threaded logging implementation
*/
static inline int strcpy_cutoff (char *dest, const char *src, int cutoff)
{
unsigned int len;
if (cutoff == -1) {
strcpy (dest, src);
return (strlen (dest));
} else {
assert (cutoff > 0);
strncpy (dest, src, cutoff);
dest[cutoff] = '\0';
len = strlen (dest);
if (len != cutoff) {
memset (&dest[len], ' ', cutoff - len);
}
}
return (cutoff);
}
/*
* %s SUBSYSTEM
* %n FUNCTION NAME
* %f FILENAME
* %l FILELINE
* %p PRIORITY
* %t TIMESTAMP
* %b BUFFER
- *
+ *
* any number between % and character specify field length to pad or chop
*/
static void log_printf_to_logs (
const char *subsys,
const char *file_name,
const char *function_name,
int file_line,
unsigned int level,
const char *buffer)
{
char output_buffer[COMBINE_BUFFER_SIZE];
char char_time[128];
char line_no[30];
unsigned int format_buffer_idx = 0;
unsigned int output_buffer_idx = 0;
struct timeval tv;
int cutoff;
unsigned int len;
int subsysid;
subsysid = _logsys_config_subsys_get(subsys);
if (subsysid <= - 1) {
return;
}
while (format_buffer[format_buffer_idx]) {
cutoff = -1;
if (format_buffer[format_buffer_idx] == '%') {
format_buffer_idx += 1;
if (isdigit (format_buffer[format_buffer_idx])) {
cutoff = atoi (&format_buffer[format_buffer_idx]);
}
while (isdigit (format_buffer[format_buffer_idx])) {
format_buffer_idx += 1;
}
-
+
switch (format_buffer[format_buffer_idx]) {
case 's':
len = strcpy_cutoff (&output_buffer[output_buffer_idx], subsys, cutoff);
output_buffer_idx += len;
break;
case 'n':
len = strcpy_cutoff (&output_buffer[output_buffer_idx], function_name, cutoff);
output_buffer_idx += len;
break;
case 'f':
len = strcpy_cutoff (&output_buffer[output_buffer_idx], file_name, cutoff);
output_buffer_idx += len;
break;
case 'l':
sprintf (line_no, "%d", file_line);
len = strcpy_cutoff (&output_buffer[output_buffer_idx], line_no, cutoff);
output_buffer_idx += len;
break;
case 'p':
break;
case 't':
gettimeofday (&tv, NULL);
(void)strftime (char_time, sizeof (char_time), "%b %e %k:%M:%S", localtime ((time_t *)&tv.tv_sec));
len = strcpy_cutoff (&output_buffer[output_buffer_idx], char_time, cutoff);
output_buffer_idx += len;
break;
case 'b':
len = strcpy_cutoff (&output_buffer[output_buffer_idx], buffer, cutoff);
output_buffer_idx += len;
break;
}
format_buffer_idx += 1;
} else {
output_buffer[output_buffer_idx++] = format_buffer[format_buffer_idx++];
}
}
output_buffer[output_buffer_idx] = '\0';
/*
* Output to syslog
*/
if ((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_SYSLOG) &&
- ((level <= logsys_loggers[subsysid].syslog_priority) ||
+ ((level <= logsys_loggers[subsysid].syslog_priority) ||
(logsys_loggers[subsysid].debug != 0))) {
syslog (level | logsys_loggers[subsysid].syslog_facility, "%s", output_buffer);
}
/*
* Terminate string with \n \0
*/
output_buffer[output_buffer_idx++] = '\n';
output_buffer[output_buffer_idx] = '\0';
/*
* Output to configured file
*/
if (((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_FILE) &&
(logsys_loggers[subsysid].logfile_fp != NULL)) &&
((level <= logsys_loggers[subsysid].logfile_priority) ||
(logsys_loggers[subsysid].debug != 0))) {
/*
* Output to a file
*/
if ((fwrite (output_buffer, strlen (output_buffer), 1,
logsys_loggers[subsysid].logfile_fp) < 1) ||
(fflush (logsys_loggers[subsysid].logfile_fp) == EOF)) {
char tmpbuffer[1024];
/*
* if we are here, it's bad.. it's really really bad.
* Best thing would be to light a candle in a church
* and pray.
*/
snprintf(tmpbuffer, sizeof(tmpbuffer),
"LOGSYS EMERGENCY: %s Unable to write to %s.",
logsys_loggers[subsysid].subsys,
logsys_loggers[subsysid].logfile);
pthread_mutex_lock (&logsys_config_mutex);
logsys_close_logfile(subsysid);
logsys_loggers[subsysid].mode &= ~LOGSYS_MODE_OUTPUT_FILE;
pthread_mutex_unlock (&logsys_config_mutex);
log_printf_to_logs(logsys_loggers[subsysid].subsys,
__FILE__, __FUNCTION__, __LINE__,
LOGSYS_LEVEL_EMERG, tmpbuffer);
}
}
/*
* Output to stderr
*/
if ((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_STDERR) &&
((level <= logsys_loggers[subsysid].logfile_priority) ||
(logsys_loggers[subsysid].debug != 0))) {
if (write (STDERR_FILENO, output_buffer, strlen (output_buffer)) < 0) {
char tmpbuffer[1024];
/*
* if we are here, it's bad.. it's really really bad.
* Best thing would be to light 20 candles for each saint
* in the calendar and pray a lot...
*/
pthread_mutex_lock (&logsys_config_mutex);
logsys_loggers[subsysid].mode &= ~LOGSYS_MODE_OUTPUT_STDERR;
pthread_mutex_unlock (&logsys_config_mutex);
snprintf(tmpbuffer, sizeof(tmpbuffer),
"LOGSYS EMERGENCY: %s Unable to write to STDERR.",
logsys_loggers[subsysid].subsys);
log_printf_to_logs(logsys_loggers[subsysid].subsys,
__FILE__, __FUNCTION__, __LINE__,
LOGSYS_LEVEL_EMERG, tmpbuffer);
}
}
}
static void record_print (const char *buf)
{
const int *buf_uint32t = (const int *)buf;
unsigned int rec_size = buf_uint32t[0];
unsigned int rec_ident = buf_uint32t[1];
unsigned int file_line = buf_uint32t[2];
unsigned int level = rec_ident >> 28;
unsigned int i;
unsigned int words_processed;
unsigned int arg_size_idx;
const void *arguments[64];
unsigned int arg_count;
arg_size_idx = 4;
words_processed = 4;
arg_count = 0;
for (i = 0; words_processed < rec_size; i++) {
arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
arg_size_idx += buf_uint32t[arg_size_idx] + 1;
words_processed += buf_uint32t[arg_size_idx] + 1;
}
/*
* (char *)arguments[0] -> subsystem
* (char *)arguments[1] -> file_name
* (char *)arguments[2] -> function_name
* (char *)arguments[3] -> message
*/
log_printf_to_logs (
(char *)arguments[0],
(char *)arguments[1],
(char *)arguments[2],
file_line,
(level-1),
(char *)arguments[3]);
}
static int record_read (char *buf, int rec_idx, int *log_msg) {
unsigned int rec_size;
unsigned int rec_ident;
int firstcopy, secondcopy;
rec_size = flt_data[rec_idx];
rec_ident = flt_data[(rec_idx + 1) % flt_data_size];
/*
* Not a log record
*/
if ((rec_ident & LOGSYS_TAG_LOG) == 0) {
*log_msg = 0;
return ((rec_idx + rec_size) % flt_data_size);
}
/*
* A log record
*/
*log_msg = 1;
firstcopy = rec_size;
secondcopy = 0;
if (firstcopy + rec_idx > flt_data_size) {
firstcopy = flt_data_size - rec_idx;
secondcopy -= firstcopy - rec_size;
}
memcpy (&buf[0], &flt_data[rec_idx], firstcopy << 2);
if (secondcopy) {
memcpy (&buf[(firstcopy << 2)], &flt_data[0], secondcopy << 2);
}
return ((rec_idx + rec_size) % flt_data_size);
}
static inline void wthread_signal (void)
{
if (wthread_active == 0) {
return;
}
pthread_mutex_lock (&logsys_cond_mutex);
pthread_cond_signal (&logsys_cond);
pthread_mutex_unlock (&logsys_cond_mutex);
}
static inline void wthread_wait (void)
{
pthread_mutex_lock (&logsys_cond_mutex);
pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
pthread_mutex_unlock (&logsys_cond_mutex);
}
static inline void wthread_wait_locked (void)
{
pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
pthread_mutex_unlock (&logsys_cond_mutex);
}
static void *logsys_worker_thread (void *data) __attribute__((__noreturn__));
static void *logsys_worker_thread (void *data)
{
int log_msg;
char buf[COMBINE_BUFFER_SIZE];
/*
* Signal wthread_create that the initialization process may continue
*/
wthread_signal ();
logsys_lock();
log_rec_idx = flt_data[FDTAIL_INDEX];
logsys_unlock();
for (;;) {
wthread_wait ();
/*
* Read and copy the logging record index position
* It may have been updated by records_reclaim if
* messages were lost or or log_rec on the first new
* logging record available
*/
/*
* Process any pending log messages here
*/
for (;;) {
logsys_lock();
if (log_requests_lost > 0) {
printf ("lost %d log requests\n", log_requests_lost);
log_requests_pending -= log_requests_lost;
log_requests_lost = 0;
}
if (log_requests_pending == 0) {
logsys_unlock();
break;
}
log_rec_idx = record_read (buf, log_rec_idx, &log_msg);
if (log_msg) {
log_requests_pending -= 1;
}
logsys_unlock();
/*
* print the stored buffer
*/
if (log_msg) {
record_print (buf);
}
}
if (wthread_should_exit) {
pthread_exit (NULL);
}
}
}
static void wthread_create (void)
{
int res;
if (wthread_active) {
return;
}
wthread_active = 1;
pthread_mutex_init (&logsys_cond_mutex, NULL);
pthread_cond_init (&logsys_cond, NULL);
pthread_mutex_lock (&logsys_cond_mutex);
res = pthread_create (&logsys_thread_id, NULL,
logsys_worker_thread, NULL);
/*
* Wait for thread to be started
*/
wthread_wait_locked ();
}
static int _logsys_config_subsys_get_unlocked (const char *subsys)
{
unsigned int i;
if (!subsys) {
return LOGSYS_MAX_SUBSYS_COUNT;
}
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
}
return (-1);
}
static void syslog_facility_reconf (void)
{
closelog();
openlog(logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].subsys,
LOG_CONS|LOG_PID,
logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].syslog_facility);
}
/*
* this is always invoked within the mutex, so it's safe to parse the
* whole thing as we need.
*/
static void logsys_close_logfile (
int subsysid)
{
int i;
if ((logsys_loggers[subsysid].logfile_fp == NULL) &&
(logsys_loggers[subsysid].logfile == NULL)) {
return;
}
/*
* if there is another subsystem or system using the same fp,
* then we clean our own structs, but we can't close the file
* as it is in use by somebody else.
* Only the last users will be allowed to perform the fclose.
*/
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
if ((logsys_loggers[i].logfile_fp == logsys_loggers[subsysid].logfile_fp) &&
(i != subsysid)) {
logsys_loggers[subsysid].logfile = NULL;
logsys_loggers[subsysid].logfile_fp = NULL;
return;
}
}
/*
* if we are here, we are the last users of that fp, so we can safely
* close it.
*/
fclose (logsys_loggers[subsysid].logfile_fp);
logsys_loggers[subsysid].logfile_fp = NULL;
free (logsys_loggers[subsysid].logfile);
logsys_loggers[subsysid].logfile = NULL;
}
/*
* we need a version that can work when somebody else is already
* holding a config mutex lock or we will never get out of here
*/
static int logsys_config_file_set_unlocked (
int subsysid,
const char **error_string,
const char *file)
{
static char error_string_response[512];
int i;
logsys_close_logfile(subsysid);
if ((file == NULL) ||
(strcmp(logsys_loggers[subsysid].subsys, "") == 0)) {
return (0);
}
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
if ((logsys_loggers[i].logfile != NULL) &&
(strcmp (logsys_loggers[i].logfile, file) == 0) &&
(i != subsysid)) {
logsys_loggers[subsysid].logfile =
logsys_loggers[i].logfile;
logsys_loggers[subsysid].logfile_fp =
logsys_loggers[i].logfile_fp;
return (0);
}
}
logsys_loggers[subsysid].logfile = strdup(file);
if (logsys_loggers[subsysid].logfile == NULL) {
snprintf (error_string_response,
sizeof(error_string_response),
"Unable to allocate memory for logfile '%s'\n",
file);
*error_string = error_string_response;
return (-1);
}
logsys_loggers[subsysid].logfile_fp = fopen (file, "a+");
if (logsys_loggers[subsysid].logfile_fp == NULL) {
free(logsys_loggers[subsysid].logfile);
logsys_loggers[subsysid].logfile = NULL;
snprintf (error_string_response,
sizeof(error_string_response),
"Can't open logfile '%s' for reason (%s).\n",
file, strerror (errno));
*error_string = error_string_response;
return (-1);
}
return (0);
}
static void logsys_subsys_init (
const char *subsys,
int subsysid)
{
if (logsys_system_needs_init == LOGSYS_LOGGER_NEEDS_INIT) {
logsys_loggers[subsysid].init_status =
LOGSYS_LOGGER_NEEDS_INIT;
} else {
memcpy(&logsys_loggers[subsysid],
&logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT],
sizeof(logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT]));
logsys_loggers[subsysid].tags = LOGSYS_TAG_LOG;
- logsys_loggers[subsysid].init_status =
+ logsys_loggers[subsysid].init_status =
LOGSYS_LOGGER_INIT_DONE;
}
strncpy (logsys_loggers[subsysid].subsys, subsys,
LOGSYS_MAX_SUBSYS_NAMELEN);
}
/*
* Internal API - exported
*/
int _logsys_system_setup(
const char *mainsystem,
unsigned int mode,
unsigned int debug,
const char *logfile,
int logfile_priority,
int syslog_facility,
int syslog_priority,
unsigned int tags)
{
int i;
const char *errstr;
char tempsubsys[LOGSYS_MAX_SUBSYS_NAMELEN];
i = LOGSYS_MAX_SUBSYS_COUNT;
pthread_mutex_lock (&logsys_config_mutex);
snprintf(logsys_loggers[i].subsys,
LOGSYS_MAX_SUBSYS_NAMELEN,
"%s", mainsystem);
logsys_loggers[i].mode = mode;
logsys_loggers[i].debug = debug;
if ((logfile) && strlen(logfile) > 0) {
if (logsys_config_file_set_unlocked (i, &errstr, logfile) < 0) {
pthread_mutex_unlock (&logsys_config_mutex);
return (-1);
}
}
logsys_loggers[i].logfile_priority = logfile_priority;
logsys_loggers[i].syslog_facility = syslog_facility;
logsys_loggers[i].syslog_priority = syslog_priority;
syslog_facility_reconf();
logsys_loggers[i].tags = tags;
logsys_loggers[i].init_status = LOGSYS_LOGGER_INIT_DONE;
logsys_system_needs_init = LOGSYS_LOGGER_INIT_DONE;
for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
if ((strcmp (logsys_loggers[i].subsys, "") != 0) &&
(logsys_loggers[i].init_status ==
LOGSYS_LOGGER_NEEDS_INIT)) {
strncpy (tempsubsys, logsys_loggers[i].subsys,
LOGSYS_MAX_SUBSYS_NAMELEN);
logsys_subsys_init(tempsubsys, i);
}
}
pthread_mutex_unlock (&logsys_config_mutex);
return (0);
}
unsigned int _logsys_subsys_create (const char *subsys)
{
int i;
assert (subsys != NULL);
pthread_mutex_lock (&logsys_config_mutex);
i = _logsys_config_subsys_get_unlocked (subsys);
if ((i > -1) && (i < LOGSYS_MAX_SUBSYS_COUNT)) {
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
if (strcmp (logsys_loggers[i].subsys, "") == 0) {
- logsys_subsys_init(subsys, i);
+ logsys_subsys_init(subsys, i);
break;
}
}
assert(i < LOGSYS_MAX_SUBSYS_COUNT);
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
int _logsys_wthread_create (void)
{
- if (((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_FORK) == 0) &&
+ if (((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_FORK) == 0) &&
((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) != 0)) {
wthread_create();
atexit (logsys_atexit);
}
return (0);
}
int _logsys_rec_init (unsigned int size)
{
/*
* First record starts at zero
* Last record ends at zero
*/
flt_data = malloc ((size + 2) * sizeof (unsigned int));
if (flt_data == NULL) {
return (-1);
}
flt_data_size = size;
flt_data[FDHEAD_INDEX] = 0;
flt_data[FDTAIL_INDEX] = 0;
#if defined(HAVE_PTHREAD_SPIN_LOCK)
pthread_spin_init (&logsys_idx_spinlock, 0);
#endif
return (0);
}
/*
* u32 RECORD SIZE
* u32 record ident
* u32 arg count
* u32 file line
* u32 subsys length
* buffer null terminated subsys
* u32 filename length
* buffer null terminated filename
* u32 filename length
* buffer null terminated function
* u32 arg1 length
* buffer arg1
* ... repeats length & arg
*/
void _logsys_log_rec (
int subsysid,
const char *function_name,
const char *file_name,
int file_line,
unsigned int rec_ident,
...)
{
va_list ap;
const void *buf_args[64];
unsigned int buf_len[64];
unsigned int i;
unsigned int idx;
unsigned int arguments = 0;
unsigned int record_reclaim_size;
unsigned int index_start;
int words_written;
record_reclaim_size = 0;
-
+
/*
* Decode VA Args
*/
va_start (ap, rec_ident);
arguments = 3;
for (;;) {
assert (arguments < 64);
buf_args[arguments] = va_arg (ap, void *);
if (buf_args[arguments] == LOGSYS_REC_END) {
break;
}
buf_len[arguments] = va_arg (ap, int);
record_reclaim_size += ((buf_len[arguments] + 3) >> 2) + 1;
arguments++;
}
va_end (ap);
/*
* Encode logsys subsystem identity, filename, and function
*/
buf_args[0] = logsys_loggers[subsysid].subsys;
buf_len[0] = strlen (logsys_loggers[subsysid].subsys) + 1;
buf_args[1] = file_name;
buf_len[1] = strlen (file_name) + 1;
buf_args[2] = function_name;
buf_len[2] = strlen (function_name) + 1;
for (i = 0; i < 3; i++) {
record_reclaim_size += ((buf_len[i] + 3) >> 2) + 1;
}
idx = flt_data[FDHEAD_INDEX];
index_start = idx;
/*
* Reclaim data needed for record including 4 words for the header
*/
records_reclaim (idx, record_reclaim_size + 4);
/*
* Write record size of zero and rest of header information
*/
flt_data[idx++] = 0;
idx_word_step(idx);
flt_data[idx++] = rec_ident;
idx_word_step(idx);
flt_data[idx++] = file_line;
idx_word_step(idx);
flt_data[idx++] = records_written;
idx_word_step(idx);
/*
* Encode all of the arguments into the log message
*/
for (i = 0; i < arguments; i++) {
unsigned int bytes;
unsigned int full_words;
unsigned int total_words;
bytes = buf_len[i];
full_words = bytes >> 2;
total_words = (bytes + 3) >> 2;
flt_data[idx++] = total_words;
idx_word_step(idx);
/*
* determine if this is a wrapped write or normal write
*/
if (idx + total_words < flt_data_size) {
/*
* dont need to wrap buffer
*/
my_memcpy_32bit (&flt_data[idx], buf_args[i], full_words);
if (bytes % 4) {
my_memcpy_8bit ((char *)&flt_data[idx + full_words],
((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
}
} else {
/*
* need to wrap buffer
*/
unsigned int first;
unsigned int second;
first = flt_data_size - idx;
if (first > full_words) {
first = full_words;
}
second = full_words - first;
my_memcpy_32bit (&flt_data[idx],
(const int *)buf_args[i], first);
my_memcpy_32bit (&flt_data[0],
(const int *)(((const unsigned char *)buf_args[i]) + (first << 2)),
second);
if (bytes % 4) {
my_memcpy_8bit ((char *)&flt_data[0 + second],
((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
}
}
idx += total_words;
idx_buffer_step (idx);
}
words_written = idx - index_start;
if (words_written < 0) {
words_written += flt_data_size;
}
/*
* Commit the write of the record size now that the full record
* is in the memory buffer
*/
flt_data[index_start] = words_written;
/*
- * If the index of the current head equals the current log_rec_idx,
+ * If the index of the current head equals the current log_rec_idx,
* and this is not a log_printf operation, set the log_rec_idx to
* the new head position and commit the new head.
*/
logsys_lock();
if (rec_ident & LOGSYS_TAG_LOG) {
log_requests_pending += 1;
}
if (log_requests_pending == 0) {
log_rec_idx = idx;
}
flt_data[FDHEAD_INDEX] = idx;
logsys_unlock();
records_written++;
}
void _logsys_log_printf (
int subsysid,
const char *function_name,
const char *file_name,
int file_line,
unsigned int level,
const char *format,
...)
{
char logsys_print_buffer[COMBINE_BUFFER_SIZE];
unsigned int len;
va_list ap;
if (subsysid <= -1) {
subsysid = LOGSYS_MAX_SUBSYS_COUNT;
}
if ((level > logsys_loggers[subsysid].syslog_priority) &&
(level > logsys_loggers[subsysid].logfile_priority)) {
return;
}
va_start (ap, format);
len = vsprintf (logsys_print_buffer, format, ap);
va_end (ap);
if (logsys_print_buffer[len - 1] == '\n') {
logsys_print_buffer[len - 1] = '\0';
len -= 1;
}
/*
* Create a log record
*/
_logsys_log_rec (subsysid,
function_name,
file_name,
file_line,
(level+1) << 28,
logsys_print_buffer, len + 1,
LOGSYS_REC_END);
if ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) == 0) {
/*
* Output (and block) if the log mode is not threaded otherwise
* expect the worker thread to output the log data once signaled
*/
log_printf_to_logs (logsys_loggers[subsysid].subsys,
file_name, function_name, file_line, level,
logsys_print_buffer);
} else {
/*
* Signal worker thread to display logging output
*/
wthread_signal ();
}
}
int _logsys_config_subsys_get (const char *subsys)
{
unsigned int i;
pthread_mutex_lock (&logsys_config_mutex);
i = _logsys_config_subsys_get_unlocked (subsys);
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
/*
* External Configuration and Initialization API
*/
void logsys_fork_completed (void)
{
logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode &= ~LOGSYS_MODE_FORK;
_logsys_wthread_create ();
}
unsigned int logsys_config_mode_set (const char *subsys, unsigned int mode)
{
int i;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i >= 0) {
logsys_loggers[i].mode = mode;
i = 0;
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
logsys_loggers[i].mode = mode;
}
i = 0;
}
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
unsigned int logsys_config_mode_get (const char *subsys)
{
int i;
i = _logsys_config_subsys_get (subsys);
if (i < 0) {
return i;
}
return logsys_loggers[i].mode;
}
unsigned int logsys_config_tags_set (const char *subsys, unsigned int tags)
{
int i;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i >= 0) {
logsys_loggers[i].tags = tags;
i = 0;
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
logsys_loggers[i].tags = tags;
}
i = 0;
}
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
unsigned int logsys_config_tags_get (const char *subsys)
{
int i;
i = _logsys_config_subsys_get (subsys);
if (i < 0) {
return i;
}
return logsys_loggers[i].tags;
}
int logsys_config_file_set (
const char *subsys,
const char **error_string,
const char *file)
{
int i;
int res;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i < 0) {
res = i;
} else {
res = logsys_config_file_set_unlocked(i, error_string, file);
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
res = logsys_config_file_set_unlocked(i, error_string, file);
if (res < 0) {
break;
}
}
}
pthread_mutex_unlock (&logsys_config_mutex);
return res;
}
int logsys_format_set (const char *format)
{
int ret = 0;
pthread_mutex_lock (&logsys_config_mutex);
if (format_buffer) {
free(format_buffer);
format_buffer = NULL;
}
format_buffer = strdup(format ? format : "[%6s] %b");
if (format_buffer == NULL) {
ret = -1;
}
pthread_mutex_unlock (&logsys_config_mutex);
return ret;
}
char *logsys_format_get (void)
{
return format_buffer;
}
unsigned int logsys_config_syslog_facility_set (
const char *subsys,
unsigned int facility)
{
int i;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i >= 0) {
logsys_loggers[i].syslog_facility = facility;
if (i == LOGSYS_MAX_SUBSYS_COUNT) {
syslog_facility_reconf();
}
i = 0;
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
logsys_loggers[i].syslog_facility = facility;
}
syslog_facility_reconf();
i = 0;
}
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
unsigned int logsys_config_syslog_priority_set (
const char *subsys,
unsigned int priority)
{
int i;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i >= 0) {
logsys_loggers[i].syslog_priority = priority;
i = 0;
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
logsys_loggers[i].syslog_priority = priority;
}
i = 0;
}
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
unsigned int logsys_config_logfile_priority_set (
const char *subsys,
unsigned int priority)
{
int i;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i >= 0) {
logsys_loggers[i].logfile_priority = priority;
i = 0;
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
logsys_loggers[i].logfile_priority = priority;
}
i = 0;
}
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
unsigned int logsys_config_debug_set (
const char *subsys,
unsigned int debug)
{
int i;
pthread_mutex_lock (&logsys_config_mutex);
if (subsys != NULL) {
i = _logsys_config_subsys_get_unlocked (subsys);
if (i >= 0) {
logsys_loggers[i].debug = debug;
i = 0;
}
} else {
for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
logsys_loggers[i].debug = debug;
}
i = 0;
}
pthread_mutex_unlock (&logsys_config_mutex);
return i;
}
int logsys_facility_id_get (const char *name)
{
unsigned int i;
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (strcasecmp(name, facilitynames[i].c_name) == 0) {
return (facilitynames[i].c_val);
}
}
return (-1);
}
const char *logsys_facility_name_get (unsigned int facility)
{
unsigned int i;
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (facility == facilitynames[i].c_val) {
return (facilitynames[i].c_name);
}
}
return (NULL);
}
int logsys_priority_id_get (const char *name)
{
unsigned int i;
for (i = 0; prioritynames[i].c_name != NULL; i++) {
if (strcasecmp(name, prioritynames[i].c_name) == 0) {
return (prioritynames[i].c_val);
}
}
return (-1);
}
const char *logsys_priority_name_get (unsigned int priority)
{
unsigned int i;
for (i = 0; prioritynames[i].c_name != NULL; i++) {
if (priority == prioritynames[i].c_val) {
return (prioritynames[i].c_name);
}
}
return (NULL);
}
int logsys_tag_id_get (const char *name)
{
unsigned int i;
for (i = 0; tagnames[i].c_name != NULL; i++) {
if (strcasecmp(name, tagnames[i].c_name) == 0) {
return (tagnames[i].c_val);
}
}
return (-1);
}
const char *logsys_tag_name_get (unsigned int tag)
{
unsigned int i;
for (i = 0; tagnames[i].c_name != NULL; i++) {
if (tag == tagnames[i].c_val) {
return (tagnames[i].c_name);
}
}
return (NULL);
}
int logsys_log_rec_store (const char *filename)
{
int fd;
ssize_t written_size;
size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int);
fd = open (filename, O_CREAT|O_RDWR, 0700);
if (fd < 0) {
return (-1);
}
written_size = write (fd, flt_data, size_to_write);
if (close (fd) != 0)
return (-1);
if (written_size < 0) {
return (-1);
} else if ((size_t)written_size != size_to_write) {
return (-1);
}
return (0);
}
void logsys_atexit (void)
{
if (wthread_active) {
wthread_should_exit = 1;
wthread_signal ();
pthread_join (logsys_thread_id, NULL);
}
}
void logsys_flush (void)
{
wthread_signal ();
}
diff --git a/exec/main.c b/exec/main.c
index eb9779fd..6392c744 100644
--- a/exec/main.c
+++ b/exec/main.c
@@ -1,951 +1,951 @@
/*
* Copyright (c) 2002-2006 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <pthread.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <corosync/swab.h>
#include <corosync/corotypes.h>
#include <corosync/list.h>
#include <corosync/queue.h>
#include <corosync/lcr/lcr_ifact.h>
#include <corosync/totem/coropoll.h>
#include <corosync/totem/totempg.h>
#include <corosync/engine/objdb.h>
#include <corosync/engine/config.h>
#include <corosync/engine/logsys.h>
#include "quorum.h"
#include "totemsrp.h"
#include "mempool.h"
#include "mainconfig.h"
#include "totemconfig.h"
#include "main.h"
#include "sync.h"
#include "tlist.h"
#include "coroipcs.h"
#include "timer.h"
#include "util.h"
#include "apidef.h"
#include "service.h"
#include "schedwrk.h"
#include "version.h"
LOGSYS_DECLARE_SYSTEM ("corosync",
LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_THREADED | LOGSYS_MODE_FORK,
0,
NULL,
LOG_INFO,
LOG_DAEMON,
LOG_INFO,
0,
NULL,
1000000);
LOGSYS_DECLARE_SUBSYS ("MAIN");
#define SERVER_BACKLOG 5
static int sched_priority = 0;
static unsigned int service_count = 32;
#if defined(HAVE_PTHREAD_SPIN_LOCK)
static pthread_spinlock_t serialize_spin;
#else
static pthread_mutex_t serialize_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
static struct totem_logging_configuration totem_logging_configuration;
static char delivery_data[MESSAGE_SIZE_MAX];
static int num_config_modules;
static struct config_iface_ver0 *config_modules[MAX_DYNAMIC_SERVICES];
static struct objdb_iface_ver0 *objdb = NULL;
static struct corosync_api_v1 *api = NULL;
static struct ug_config ug_config;
unsigned long long *(*main_clm_get_by_nodeid) (unsigned int node_id);
hdb_handle_t corosync_poll_handle;
static void sigusr2_handler (int num)
{
int i;
for (i = 0; ais_service[i]; i++) {
if (ais_service[i]->exec_dump_fn) {
ais_service[i]->exec_dump_fn ();
}
}
}
static void *corosync_exit (void *arg) __attribute__((__noreturn__));
static void *corosync_exit (void *arg)
{
if (api) {
corosync_service_unlink_all (api);
}
#ifdef DEBUG_MEMPOOL
int stats_inuse[MEMPOOL_GROUP_SIZE];
int stats_avail[MEMPOOL_GROUP_SIZE];
int stats_memoryused[MEMPOOL_GROUP_SIZE];
int i;
mempool_getstats (stats_inuse, stats_avail, stats_memoryused);
log_printf (LOGSYS_LEVEL_DEBUG, "Memory pools:\n");
for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
log_printf (LOGSYS_LEVEL_DEBUG, "order %d size %d inuse %d avail %d memory used %d\n",
i, 1<<i, stats_inuse[i], stats_avail[i], stats_memoryused[i]);
}
#endif
poll_stop (0);
totempg_finalize ();
coroipcs_ipc_exit ();
corosync_exit_error (AIS_DONE_EXIT);
}
pthread_t corosync_exit_thread;
-static void init_shutdown(void *data)
+static void init_shutdown(void *data)
{
pthread_create (&corosync_exit_thread, NULL, corosync_exit, NULL);
}
static poll_timer_handle shutdown_handle;
static void sigquit_handler (int num)
{
/* avoid creating threads from within the interrupt context */
poll_timer_add (corosync_poll_handle, 500, NULL, init_shutdown, &shutdown_handle);
}
static void sigsegv_handler (int num)
{
(void)signal (SIGSEGV, SIG_DFL);
logsys_atexit();
logsys_log_rec_store (LOCALSTATEDIR "/lib/corosync/fdata");
raise (SIGSEGV);
}
static void sigabrt_handler (int num)
{
(void)signal (SIGABRT, SIG_DFL);
logsys_atexit();
logsys_log_rec_store (LOCALSTATEDIR "/lib/corosync/fdata");
raise (SIGABRT);
}
#define LOCALHOST_IP inet_addr("127.0.0.1")
hdb_handle_t corosync_group_handle;
struct totempg_group corosync_group = {
.group = "a",
.group_len = 1
};
static void sigintr_handler (int signum)
{
poll_timer_add (corosync_poll_handle, 500, NULL,
init_shutdown, &shutdown_handle);
}
static int pool_sizes[] = { 0, 0, 0, 0, 0, 4096, 0, 1, 0, /* 256 */
1024, 0, 1, 4096, 0, 0, 0, 0, /* 65536 */
1, 1, 1, 1, 1, 1, 1, 1, 1 };
#if defined(HAVE_PTHREAD_SPIN_LOCK)
static void serialize_lock (void)
{
pthread_spin_lock (&serialize_spin);
}
static void serialize_unlock (void)
{
pthread_spin_unlock (&serialize_spin);
}
#else
static void serialize_lock (void)
{
pthread_mutex_lock (&serialize_mutex);
}
static void serialize_unlock (void)
{
pthread_mutex_unlock (&serialize_mutex);
}
#endif
static void corosync_sync_completed (void)
{
}
static int corosync_sync_callbacks_retrieve (int sync_id,
struct sync_callbacks *callbacks)
{
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[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);
}
static struct memb_ring_id corosync_ring_id;
static void confchg_fn (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id)
{
int i;
serialize_lock ();
memcpy (&corosync_ring_id, ring_id, sizeof (struct memb_ring_id));
/*
* Call configuration change for all services
*/
for (i = 0; i < service_count; i++) {
if (ais_service[i] && ais_service[i]->confchg_fn) {
ais_service[i]->confchg_fn (configuration_type,
member_list, member_list_entries,
left_list, left_list_entries,
joined_list, joined_list_entries, ring_id);
}
}
serialize_unlock ();
}
static void priv_drop (void)
{
return; /* TODO: we are still not dropping privs */
setuid (ug_config.uid);
setegid (ug_config.gid);
}
static void corosync_mempool_init (void)
{
int res;
res = mempool_init (pool_sizes);
if (res == ENOMEM) {
log_printf (LOGSYS_LEVEL_ERROR, "Couldn't allocate memory pools, not enough memory");
corosync_exit_error (AIS_DONE_MEMPOOL_INIT);
}
}
static void corosync_tty_detach (void)
{
int fd;
/*
* Disconnect from TTY if this is not a debug run
*/
switch (fork ()) {
case -1:
corosync_exit_error (AIS_DONE_FORK);
break;
case 0:
/*
* child which is disconnected, run this process
*/
/* setset();
close (0);
close (1);
close (2);
*/
break;
default:
exit (0);
break;
}
/* Create new session */
(void)setsid();
- /*
+ /*
* Map stdin/out/err to /dev/null.
*/
fd = open("/dev/null", O_RDWR);
if (fd >= 0) {
/* dup2 to 0 / 1 / 2 (stdin / stdout / stderr) */
dup2(fd, STDIN_FILENO); /* 0 */
dup2(fd, STDOUT_FILENO); /* 1 */
dup2(fd, STDERR_FILENO); /* 2 */
/* Should be 0, but just in case it isn't... */
- if (fd > 2)
+ if (fd > 2)
close(fd);
}
}
static void corosync_setscheduler (void)
{
#if ! defined(TS_CLASS) && (defined(COROSYNC_BSD) || defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS))
struct sched_param sched_param;
int res;
sched_priority = sched_get_priority_max (SCHED_RR);
if (sched_priority != -1) {
sched_param.sched_priority = sched_priority;
res = sched_setscheduler (0, SCHED_RR, &sched_param);
if (res == -1) {
log_printf (LOGSYS_LEVEL_WARNING, "Could not set SCHED_RR at priority %d: %s\n",
sched_param.sched_priority, strerror (errno));
}
} else {
log_printf (LOGSYS_LEVEL_WARNING, "Could not get maximum scheduler priority: %s\n", strerror (errno));
sched_priority = 0;
}
#else
log_printf(LOGSYS_LEVEL_WARNING, "Scheduler priority left to default value (no OS support)\n");
#endif
}
static void corosync_mlockall (void)
{
#if !defined(COROSYNC_BSD)
int res;
#endif
struct rlimit rlimit;
rlimit.rlim_cur = RLIM_INFINITY;
rlimit.rlim_max = RLIM_INFINITY;
#ifndef COROSYNC_SOLARIS
setrlimit (RLIMIT_MEMLOCK, &rlimit);
#else
setrlimit (RLIMIT_VMEM, &rlimit);
#endif
#if defined(COROSYNC_BSD)
/* under FreeBSD a process with locked page cannot call dlopen
* code disabled until FreeBSD bug i386/93396 was solved
*/
log_printf (LOGSYS_LEVEL_WARNING, "Could not lock memory of service to avoid page faults\n");
#else
res = mlockall (MCL_CURRENT | MCL_FUTURE);
if (res == -1) {
log_printf (LOGSYS_LEVEL_WARNING, "Could not lock memory of service to avoid page faults: %s\n", strerror (errno));
};
#endif
}
static void deliver_fn (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required)
{
mar_req_header_t *header;
int pos = 0;
int i;
int service;
int fn_id;
/*
* Build buffer without iovecs to make processing easier
* This is only used for messages which are multicast with iovecs
* and self-delivered. All other mechanisms avoid the copy.
*/
if (iov_len > 1) {
for (i = 0; i < iov_len; i++) {
memcpy (&delivery_data[pos], iovec[i].iov_base, iovec[i].iov_len);
pos += iovec[i].iov_len;
assert (pos < MESSAGE_SIZE_MAX);
}
header = (mar_req_header_t *)delivery_data;
} else {
header = (mar_req_header_t *)iovec[0].iov_base;
}
if (endian_conversion_required) {
header->id = swab32 (header->id);
header->size = swab32 (header->size);
}
// assert(iovec->iov_len == header->size);
/*
* Call the proper executive handler
*/
service = header->id >> 16;
fn_id = header->id & 0xffff;
if (!ais_service[service])
return;
serialize_lock();
if (endian_conversion_required) {
assert(ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn != NULL);
ais_service[service]->exec_engine[fn_id].exec_endian_convert_fn
(header);
}
ais_service[service]->exec_engine[fn_id].exec_handler_fn
(header, nodeid);
serialize_unlock();
}
void main_get_config_modules(struct config_iface_ver0 ***modules, int *num)
{
*modules = config_modules;
*num = num_config_modules;
}
int main_mcast (
const struct iovec *iovec,
unsigned int iov_len,
unsigned int guarantee)
{
return (totempg_groups_mcast_joined (corosync_group_handle, iovec, iov_len, guarantee));
}
int message_source_is_local (const mar_message_source_t *source)
{
int ret = 0;
assert (source != NULL);
if (source->nodeid == totempg_my_nodeid_get ()) {
ret = 1;
}
return ret;
}
void message_source_set (
mar_message_source_t *source,
void *conn)
{
assert ((source != NULL) && (conn != NULL));
memset (source, 0, sizeof (mar_message_source_t));
source->nodeid = totempg_my_nodeid_get ();
source->conn = conn;
}
/*
* Provides the glue from corosync to the IPC Service
*/
static int corosync_private_data_size_get (unsigned int service)
{
return (ais_service[service]->private_data_size);
}
static coroipcs_init_fn_lvalue corosync_init_fn_get (unsigned int service)
{
return (ais_service[service]->lib_init_fn);
}
static coroipcs_exit_fn_lvalue corosync_exit_fn_get (unsigned int service)
{
return (ais_service[service]->lib_exit_fn);
}
static coroipcs_handler_fn_lvalue corosync_handler_fn_get (unsigned int service, unsigned int id)
{
return (ais_service[service]->lib_engine[id].lib_handler_fn);
}
static int corosync_security_valid (int euid, int egid)
{
if (euid == 0 || egid == 0) {
return (1);
}
if (euid == ug_config.uid || egid == ug_config.gid) {
return (1);
}
return (0);
}
static int corosync_service_available (unsigned int service)
{
return (ais_service[service] != NULL);
}
static int corosync_response_size_get (unsigned int service, unsigned int id)
{
return (ais_service[service]->lib_engine[id].response_size);
}
static int corosync_response_id_get (unsigned int service, unsigned int id)
{
return (ais_service[service]->lib_engine[id].response_id);
}
struct sending_allowed_private_data_struct {
int reserved_msgs;
};
static int corosync_sending_allowed (
unsigned int service,
- unsigned int id,
+ unsigned int id,
void *msg,
void *sending_allowed_private_data)
{
struct sending_allowed_private_data_struct *pd =
(struct sending_allowed_private_data_struct *)sending_allowed_private_data;
struct iovec reserve_iovec;
mar_req_header_t *header = (mar_req_header_t *)msg;
int sending_allowed;
reserve_iovec.iov_base = (char *)header;
reserve_iovec.iov_len = header->size;
pd->reserved_msgs = totempg_groups_joined_reserve (
corosync_group_handle,
&reserve_iovec, 1);
sending_allowed =
(corosync_quorum_is_quorate() == 1 ||
ais_service[service]->allow_inquorate == CS_LIB_ALLOW_INQUORATE) &&
((ais_service[service]->lib_engine[id].flow_control == CS_LIB_FLOW_CONTROL_NOT_REQUIRED) ||
((ais_service[service]->lib_engine[id].flow_control == CS_LIB_FLOW_CONTROL_REQUIRED) &&
(pd->reserved_msgs) &&
(sync_in_process() == 0)));
return (sending_allowed);
}
static void corosync_sending_allowed_release (void *sending_allowed_private_data)
{
struct sending_allowed_private_data_struct *pd =
(struct sending_allowed_private_data_struct *)sending_allowed_private_data;
totempg_groups_joined_release (pd->reserved_msgs);
}
static int ipc_subsys_id = -1;
static void ipc_log_printf (const char *format, ...) {
va_list ap;
va_start (ap, format);
- _logsys_log_printf (ipc_subsys_id, __FUNCTION__,
+ _logsys_log_printf (ipc_subsys_id, __FUNCTION__,
__FILE__, __LINE__, LOGSYS_LEVEL_ERROR, format, ap);
va_end (ap);
}
static void ipc_fatal_error(const char *error_msg) {
- _logsys_log_printf (ipc_subsys_id, __FUNCTION__,
+ _logsys_log_printf (ipc_subsys_id, __FUNCTION__,
__FILE__, __LINE__, LOGSYS_LEVEL_ERROR, "%s", error_msg);
exit(EXIT_FAILURE);
}
static int corosync_poll_handler_accept (
- hdb_handle_t handle,
+ hdb_handle_t handle,
int fd,
int revent,
void *context)
{
return (coroipcs_handler_accept (fd, revent, context));
}
static int corosync_poll_handler_dispatch (
- hdb_handle_t handle,
+ hdb_handle_t handle,
int fd,
int revent,
void *context)
{
return (coroipcs_handler_dispatch (fd, revent, context));
}
static void corosync_poll_accept_add (
int fd)
{
poll_dispatch_add (corosync_poll_handle, fd, POLLIN|POLLNVAL, 0,
corosync_poll_handler_accept);
}
static void corosync_poll_dispatch_add (
int fd,
void *context)
{
poll_dispatch_add (corosync_poll_handle, fd, POLLIN|POLLNVAL, context,
corosync_poll_handler_dispatch);
}
static void corosync_poll_dispatch_modify (
int fd,
int events)
{
poll_dispatch_modify (corosync_poll_handle, fd, events,
corosync_poll_handler_dispatch);
}
struct coroipcs_init_state ipc_init_state = {
.socket_name = IPC_SOCKET_NAME,
.malloc = malloc,
.free = free,
.log_printf = ipc_log_printf,
.fatal_error = ipc_fatal_error,
.security_valid = corosync_security_valid,
.service_available = corosync_service_available,
.private_data_size_get = corosync_private_data_size_get,
.serialize_lock = serialize_lock,
.serialize_unlock = serialize_unlock,
.sending_allowed = corosync_sending_allowed,
.sending_allowed_release = corosync_sending_allowed_release,
.response_size_get = corosync_response_size_get,
.response_id_get = corosync_response_id_get,
.poll_accept_add = corosync_poll_accept_add,
.poll_dispatch_add = corosync_poll_dispatch_add,
.poll_dispatch_modify = corosync_poll_dispatch_modify,
.init_fn_get = corosync_init_fn_get,
.exit_fn_get = corosync_exit_fn_get,
.handler_fn_get = corosync_handler_fn_get
};
int main (int argc, char **argv)
{
const char *error_string;
struct totem_config totem_config;
hdb_handle_t objdb_handle;
hdb_handle_t config_handle;
unsigned int config_version = 0;
void *objdb_p;
struct config_iface_ver0 *config;
void *config_p;
const char *config_iface_init;
char *config_iface;
char *iface;
int res, ch;
int background, setprio;
#if defined(HAVE_PTHREAD_SPIN_LOCK)
pthread_spin_init (&serialize_spin, 0);
#endif
/* default configuration
*/
background = 1;
setprio = 1;
-
+
while ((ch = getopt (argc, argv, "fp")) != EOF) {
-
+
switch (ch) {
case 'f':
background = 0;
logsys_config_mode_set (NULL, LOGSYS_MODE_OUTPUT_STDERR|LOGSYS_MODE_THREADED|LOGSYS_MODE_FORK);
break;
case 'p':
setprio = 0;
break;
default:
fprintf(stderr, \
"usage:\n"\
" -f : Start application in foreground.\n"\
" -p : Do not set process priority. \n");
return EXIT_FAILURE;
}
- }
+ }
if (background)
corosync_tty_detach ();
log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Executive Service RELEASE '%s'\n", RELEASE_VERSION);
log_printf (LOGSYS_LEVEL_NOTICE, "Copyright (C) 2002-2006 MontaVista Software, Inc and contributors.\n");
log_printf (LOGSYS_LEVEL_NOTICE, "Copyright (C) 2006-2008 Red Hat, Inc.\n");
(void)signal (SIGINT, sigintr_handler);
(void)signal (SIGUSR2, sigusr2_handler);
(void)signal (SIGSEGV, sigsegv_handler);
(void)signal (SIGABRT, sigabrt_handler);
(void)signal (SIGQUIT, sigquit_handler);
#if MSG_NOSIGNAL == 0
(void)signal (SIGPIPE, SIG_IGN);
#endif
-
+
corosync_timer_init (
serialize_lock,
serialize_unlock,
sched_priority);
log_printf (LOGSYS_LEVEL_NOTICE, "Corosync Executive Service: started and ready to provide service.\n");
corosync_poll_handle = poll_create ();
/*
* Load the object database interface
*/
res = lcr_ifact_reference (
&objdb_handle,
"objdb",
0,
&objdb_p,
0);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't open configuration object database component.\n");
corosync_exit_error (AIS_DONE_OBJDB);
}
objdb = (struct objdb_iface_ver0 *)objdb_p;
objdb->objdb_init ();
/*
* Initialize the corosync_api_v1 definition
*/
apidef_init (objdb);
api = apidef_get ();
num_config_modules = 0;
/*
* Bootstrap in the default configuration parser or use
* the corosync default built in parser if the configuration parser
* isn't overridden
*/
config_iface_init = getenv("COROSYNC_DEFAULT_CONFIG_IFACE");
if (!config_iface_init) {
config_iface_init = "corosync_parser";
}
/* Make a copy so we can deface it with strtok */
if ((config_iface = strdup(config_iface_init)) == NULL) {
log_printf (LOGSYS_LEVEL_ERROR, "exhausted virtual memory");
corosync_exit_error (AIS_DONE_OBJDB);
}
iface = strtok(config_iface, ":");
while (iface)
{
res = lcr_ifact_reference (
&config_handle,
iface,
config_version,
&config_p,
0);
config = (struct config_iface_ver0 *)config_p;
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't open configuration component '%s'\n", iface);
corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
}
res = config->config_readconfig(objdb, &error_string);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
}
log_printf (LOGSYS_LEVEL_NOTICE, "%s", error_string);
config_modules[num_config_modules++] = config;
iface = strtok(NULL, ":");
}
free(config_iface);
res = corosync_main_config_read (objdb, &error_string, &ug_config);
if (res == -1) {
/*
* if we are here, we _must_ flush the logsys queue
* and try to inform that we couldn't read the config.
* this is a desperate attempt before certain death
* and there is no guarantee that we can print to stderr
* nor that logsys is sending the messages where we expect.
*/
log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
fprintf(stderr, "%s", error_string);
syslog (LOGSYS_LEVEL_ERROR, "%s", error_string);
corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
}
res = totem_config_read (objdb, &totem_config, &error_string);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
}
res = totem_config_keyread (objdb, &totem_config, &error_string);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
}
res = totem_config_validate (&totem_config, &error_string);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
corosync_exit_error (AIS_DONE_MAINCONFIGREAD);
}
/*
* Set round robin realtime scheduling with priority 99
* Lock all memory to avoid page faults which may interrupt
* application healthchecking
*/
if (setprio)
corosync_setscheduler ();
corosync_mlockall ();
totem_config.totem_logging_configuration = totem_logging_configuration;
totem_config.totem_logging_configuration.log_subsys_id =
_logsys_subsys_create ("TOTEM");
totem_config.totem_logging_configuration.log_level_security = LOGSYS_LEVEL_SECURITY;
totem_config.totem_logging_configuration.log_level_error = LOGSYS_LEVEL_ERROR;
totem_config.totem_logging_configuration.log_level_warning = LOGSYS_LEVEL_WARNING;
totem_config.totem_logging_configuration.log_level_notice = LOGSYS_LEVEL_NOTICE;
totem_config.totem_logging_configuration.log_level_debug = LOGSYS_LEVEL_DEBUG;
totem_config.totem_logging_configuration.log_printf = _logsys_log_printf;
/*
* Sleep for a while to let other nodes in the cluster
* understand that this node has been away (if it was
* an corosync restart).
*/
// TODO what is this hack for? usleep(totem_config.token_timeout * 2000);
/*
* if totempg_initialize doesn't have root priveleges, it cannot
* bind to a specific interface. This only matters if
* there is more then one interface in a system, so
* in this case, only a warning is printed
*/
/*
* Join multicast group and setup delivery
* and configuration change functions
*/
totempg_initialize (
corosync_poll_handle,
&totem_config);
totempg_groups_initialize (
&corosync_group_handle,
deliver_fn,
confchg_fn);
totempg_groups_join (
corosync_group_handle,
&corosync_group,
1);
/*
* This must occur after totempg is initialized because "this_ip" must be set
*/
res = corosync_service_defaults_link_and_init (api);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "Could not initialize default services\n");
corosync_exit_error (AIS_DONE_INIT_SERVICES);
}
sync_register (corosync_sync_callbacks_retrieve, corosync_sync_completed);
/*
* Drop root privleges to user 'ais'
* TODO: Don't really need full root capabilities;
* needed capabilities are:
* CAP_NET_RAW (bindtodevice)
* CAP_SYS_NICE (setscheduler)
* CAP_IPC_LOCK (mlockall)
*/
priv_drop ();
corosync_mempool_init ();
schedwrk_init (
serialize_lock,
serialize_unlock);
ipc_subsys_id = _logsys_subsys_create ("IPC");
ipc_init_state.sched_priority = sched_priority;
coroipcs_ipc_init (&ipc_init_state);
/*
* Start main processing loop
*/
poll_run (corosync_poll_handle);
return EXIT_SUCCESS;
}
diff --git a/exec/mainconfig.h b/exec/mainconfig.h
index b40c7a83..c9ab7ea6 100644
--- a/exec/mainconfig.h
+++ b/exec/mainconfig.h
@@ -1,65 +1,65 @@
/*
* Copyright (c) 2002-2005 MontaVista Software, Inc.
* Copyright (c) 2006-2007 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.
*/
#ifndef MAINCONFIG_H_DEFINED
#define MAINCONFIG_H_DEFINED
#include <corosync/engine/objdb.h>
#include <corosync/engine/logsys.h>
/*
* All service handlers in the AIS
*/
struct dynamic_service {
char *name;
unsigned int ver;
unsigned int handle;
struct corosync_service_engine_iface_ver0 *iface_ver0;
};
#define MAX_DYNAMIC_SERVICES 128
struct ug_config {
/*
* user/group to run as
*/
int uid;
int gid;
};
extern int corosync_main_config_read (
struct objdb_iface_ver0 *objdb,
const char **error_string,
struct ug_config *ug_config);
#endif /* MAINCONFIG_H_DEFINED */
diff --git a/exec/mempool.c b/exec/mempool.c
index fbaeef51..e6cb2066 100644
--- a/exec/mempool.c
+++ b/exec/mempool.c
@@ -1,227 +1,227 @@
/*
* Copyright (c) 2003-2004 MontaVista Software, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <corosync/list.h>
#include "mempool.h"
int mempool_bytes = 0;
struct mempool_list {
struct list_head free;
short free_entries;
short used_entries;
};
struct mempool_entry {
struct list_head list;
int mempool_entry;
char mem[0];
};
struct mempool_list mempool_group[MEMPOOL_GROUP_SIZE];
#ifdef MEMPOOL_ON
int mempool_init (int pool_sizes[MEMPOOL_GROUP_SIZE])
{
int i, j;
struct mempool_entry *entry;
void *mempool;
char *p;
int bytes_to_alloc;
for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
for (j = 0; j < pool_sizes[i]; j++) {
bytes_to_alloc = sizeof (struct mempool_entry) + (1 << i) + 3;
bytes_to_alloc &= 0xFFFFFFFC;
mempool_bytes += bytes_to_alloc;
}
}
mempool = malloc (mempool_bytes);
if (mempool == 0) {
return (ENOMEM);
}
memset (mempool, 0, mempool_bytes);
for (p = (char *)mempool, i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
list_init (&mempool_group[i].free);
mempool_group[i].free_entries = pool_sizes[i];
mempool_group[i].used_entries = 0;
-
+
for (j = 0; j < pool_sizes[i]; j++) {
entry = (struct mempool_entry *)p;
entry->mempool_entry = i;
list_add (&entry->list, &mempool_group[i].free);
bytes_to_alloc = sizeof (struct mempool_entry) + (1 << i) + 3;
bytes_to_alloc &= 0xFFFFFFFC;
p += bytes_to_alloc;
}
}
return (0);
}
void *mempool_malloc (size_t size)
{
struct mempool_entry *mempool_entry;
int i;
#ifdef DEBUG
int first = 0;
int stats_inuse[MEMPOOL_GROUP_SIZE];
int stats_avail[MEMPOOL_GROUP_SIZE];
int stats_memoryused[MEMPOOL_GROUP_SIZE];
#endif
for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
#ifdef DEBUG
if (((i << 1) >= size) && first == 0) {
first = i;
}
#endif
if (((1 << i) >= size) &&
mempool_group[i].free_entries) {
-
+
mempool_group[i].used_entries += 1;
mempool_group[i].free_entries -= 1;
mempool_entry = list_entry (mempool_group[i].free.next,
struct mempool_entry, list);
list_del (mempool_group[i].free.next);
return (&mempool_entry->mem);
}
}
#ifdef DEBUG
mempool_getstats (stats_inuse, stats_avail, stats_memoryused);
printf ("MEMORY POOLS first %d %d:\n", first, size);
for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
printf ("order %d size %d inuse %d avail %d memory used %d\n",
i, 1<<i, stats_inuse[i], stats_avail[i], stats_memoryused[i]);
}
#endif
return (0);
}
void mempool_free (void *ptr) {
struct mempool_entry *mempool_entry;
mempool_entry = ((struct mempool_entry *)((unsigned long)(ptr) - (unsigned long)(&((struct mempool_entry *)0)->mem)));
mempool_group[mempool_entry->mempool_entry].free_entries += 1;
mempool_group[mempool_entry->mempool_entry].used_entries -= 1;
list_add (&mempool_entry->list, &mempool_group[mempool_entry->mempool_entry].free);
}
void *mempool_realloc (void *ptr, size_t size) {
struct mempool_entry *mempool_entry;
void *new_ptr;
mempool_entry = ((struct mempool_entry *)((unsigned long)(ptr) - (unsigned long)(&((struct mempool_entry *)0)->mem)));
-
+
if (ptr == 0 || (1 << mempool_entry->mempool_entry) < size) {
/*
* Must grow allocated block, copy memory, free old block
*/
new_ptr = (void *)mempool_malloc (size);
if (new_ptr == 0) {
return (0);
}
if (ptr) {
memcpy (new_ptr, ptr, (1 << mempool_entry->mempool_entry));
mempool_free (ptr);
}
ptr = new_ptr;
}
return (ptr);
}
char *mempool_strdup (const char *s)
{
char *mem;
mem = mempool_malloc (strlen (s));
strcpy (mem, s);
return (mem);
}
void mempool_getstats (
int stats_inuse[MEMPOOL_GROUP_SIZE],
int stats_avail[MEMPOOL_GROUP_SIZE],
int stats_memoryused[MEMPOOL_GROUP_SIZE])
{
int i;
for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) {
stats_inuse[i] = mempool_group[i].used_entries;
stats_avail[i] = mempool_group[i].free_entries;
stats_memoryused[i] = (mempool_group[i].used_entries + mempool_group[i].free_entries) * (sizeof (struct mempool_entry) + (1<<i));
}
}
#else /* MEMPOOL_ON NOT SET */
int mempool_init (int pool_sizes[MEMPOOL_GROUP_SIZE]) {
return (0);
}
void *mempool_malloc (size_t size) {
return (malloc (size));
}
void mempool_free (void *ptr) {
free (ptr);
}
void *mempool_realloc (void *ptr, size_t size) {
return (realloc (ptr, size));
}
char *mempool_strdup (const char *s) {
return (strdup (s));
}
void mempool_getstats (
int stats_inuse[MEMPOOL_GROUP_SIZE],
int stats_avail[MEMPOOL_GROUP_SIZE],
int stats_memoryused[MEMPOOL_GROUP_SIZE]) {
return;
}
#endif
diff --git a/exec/mempool.h b/exec/mempool.h
index ded58ac2..c9d9c5bb 100644
--- a/exec/mempool.h
+++ b/exec/mempool.h
@@ -1,57 +1,57 @@
/*
* Copyright (c) 2003-2004 MontaVista Software, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <corosync/list.h>
#ifndef MEMPOOL_H_DEFINED
#define MEMPOOL_H_DEFINED
#define MEMPOOL_GROUP_SIZE 24
int mempool_init (int pool_sizes[MEMPOOL_GROUP_SIZE]);
void *mempool_malloc (size_t size);
void mempool_free (void *ptr);
void *mempool_realloc (void *ptr, size_t size);
char *mempool_strdup (const char *s);
void mempool_getstats (
int stats_inuse[MEMPOOL_GROUP_SIZE],
int stats_avail[MEMPOOL_GROUP_SIZE],
int stats_memoryused[MEMPOOL_GROUP_SIZE]);
#endif /* MEMPOOL_H_DEFINED */
diff --git a/exec/service.c b/exec/service.c
index 3f07d60c..073abdbb 100644
--- a/exec/service.c
+++ b/exec/service.c
@@ -1,420 +1,420 @@
/*
* Copyright (c) 2006 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <corosync/lcr/lcr_ifact.h>
#include <corosync/swab.h>
#include <corosync/totem/totem.h>
#include "mainconfig.h"
#include "util.h"
#include <corosync/engine/logsys.h>
#include "timer.h"
#include <corosync/totem/totempg.h>
#include <corosync/totem/totemip.h>
#include "main.h"
#include "coroipcs.h"
#include <corosync/engine/coroapi.h>
#include "service.h"
LOGSYS_DECLARE_SUBSYS ("SERV");
struct default_service {
const char *name;
int ver;
};
static struct default_service default_services[] = {
{
.name = "corosync_evs",
.ver = 0,
},
{
.name = "corosync_cfg",
.ver = 0,
},
{
.name = "corosync_cpg",
.ver = 0,
},
{
.name = "corosync_confdb",
.ver = 0,
},
{
.name = "corosync_pload",
.ver = 0,
}
};
struct corosync_service_engine *ais_service[SERVICE_HANDLER_MAXIMUM_COUNT];
static hdb_handle_t object_internal_configuration_handle;
static unsigned int default_services_requested (struct corosync_api_v1 *corosync_api)
{
hdb_handle_t object_service_handle;
hdb_handle_t object_find_handle;
char *value;
/*
* Don't link default services if they have been disabled
*/
corosync_api->object_find_create (
OBJECT_PARENT_HANDLE,
"aisexec",
strlen ("aisexec"),
&object_find_handle);
if (corosync_api->object_find_next (
object_find_handle,
&object_service_handle) == 0) {
if ( ! corosync_api->object_key_get (object_service_handle,
"defaultservices",
strlen ("defaultservices"),
(void *)&value,
NULL)) {
if (value && strcmp (value, "no") == 0) {
return 0;
}
}
}
corosync_api->object_find_destroy (object_find_handle);
return (-1);
}
unsigned int corosync_service_link_and_init (
struct corosync_api_v1 *corosync_api,
const char *service_name,
unsigned int service_ver)
{
struct corosync_service_engine_iface_ver0 *iface_ver0;
void *iface_ver0_p;
hdb_handle_t handle;
struct corosync_service_engine *service;
unsigned int res;
hdb_handle_t object_service_handle;
/*
* reference the service interface
*/
iface_ver0_p = NULL;
lcr_ifact_reference (
&handle,
service_name,
service_ver,
&iface_ver0_p,
(void *)0);
iface_ver0 = (struct corosync_service_engine_iface_ver0 *)iface_ver0_p;
if (iface_ver0 == 0) {
log_printf(LOGSYS_LEVEL_ERROR, "Service failed to load '%s'.\n", service_name);
return (-1);
}
/*
* Initialize service
*/
service = iface_ver0->corosync_get_service_engine_ver0();
ais_service[service->id] = service;
if (service->config_init_fn) {
res = service->config_init_fn (corosync_api);
}
if (service->exec_init_fn) {
res = service->exec_init_fn (corosync_api);
}
/*
* Store service in object database
*/
corosync_api->object_create (object_internal_configuration_handle,
&object_service_handle,
"service",
strlen ("service"));
corosync_api->object_key_create (object_service_handle,
"name",
strlen ("name"),
service_name,
strlen (service_name) + 1);
corosync_api->object_key_create (object_service_handle,
"ver",
strlen ("ver"),
&service_ver,
sizeof (service_ver));
res = corosync_api->object_key_create (object_service_handle,
"handle",
strlen ("handle"),
&handle,
sizeof (handle));
corosync_api->object_key_create (object_service_handle,
"service_id",
strlen ("service_id"),
&service->id,
sizeof (service->id));
log_printf (LOGSYS_LEVEL_NOTICE, "Service initialized '%s'\n", service->name);
return (res);
}
static int corosync_service_unlink_common (
struct corosync_api_v1 *corosync_api,
hdb_handle_t object_service_handle,
const char *service_name,
- unsigned int service_version)
+ unsigned int service_version)
{
unsigned int res;
unsigned short *service_id;
hdb_handle_t *found_service_handle;
res = corosync_api->object_key_get (object_service_handle,
"handle",
strlen ("handle"),
(void *)&found_service_handle,
NULL);
-
+
res = corosync_api->object_key_get (object_service_handle,
"service_id",
strlen ("service_id"),
(void *)&service_id,
NULL);
-
+
log_printf(LOGSYS_LEVEL_NOTICE, "Unloading corosync component: %s v%u\n",
service_name, service_version);
if (ais_service[*service_id]->exec_exit_fn) {
ais_service[*service_id]->exec_exit_fn ();
}
ais_service[*service_id] = NULL;
-
- return lcr_ifact_release (*found_service_handle);
+
+ return lcr_ifact_release (*found_service_handle);
}
extern unsigned int corosync_service_unlink_and_exit (
struct corosync_api_v1 *corosync_api,
const char *service_name,
unsigned int service_ver)
{
unsigned int res;
hdb_handle_t object_service_handle;
char *found_service_name;
unsigned int *found_service_ver;
hdb_handle_t object_find_handle;
corosync_api->object_find_create (
object_internal_configuration_handle,
"service",
strlen ("service"),
&object_find_handle);
while (corosync_api->object_find_next (
object_find_handle,
&object_service_handle) == 0) {
corosync_api->object_key_get (object_service_handle,
"name",
strlen ("name"),
(void *)&found_service_name,
NULL);
corosync_api->object_key_get (object_service_handle,
"ver",
strlen ("ver"),
(void *)&found_service_ver,
NULL);
/*
* If service found and linked exit it
*/
if ((strcmp (service_name, found_service_name) == 0) &&
(service_ver == *found_service_ver)) {
res = corosync_service_unlink_common (
corosync_api, object_service_handle,
service_name, service_ver);
corosync_api->object_destroy (object_service_handle);
return res;
}
}
corosync_api->object_find_destroy (object_find_handle);
return (-1);
}
extern unsigned int corosync_service_unlink_all (
struct corosync_api_v1 *corosync_api)
{
char *service_name;
unsigned int *service_ver;
hdb_handle_t object_service_handle;
hdb_handle_t object_find_handle;
- int found;
+ int found;
log_printf(LOGSYS_LEVEL_NOTICE, "Unloading all corosync components\n");
/*
* TODO
* Deleting of keys not supported during iteration at this time
* hence this ugly hack
*/
while(corosync_api->object_find_create (
object_internal_configuration_handle,
"service",
strlen ("service"),
&object_find_handle) == 0)
{
found = 0;
while(corosync_api->object_find_next (
object_find_handle,
&object_service_handle) == 0)
found = 1;
if(!found)
break;
corosync_api->object_key_get (
object_service_handle,
"name",
strlen ("name"),
(void *)&service_name,
NULL);
corosync_api->object_key_get (
object_service_handle,
"ver",
strlen ("ver"),
(void *)&service_ver,
NULL);
corosync_service_unlink_common (
corosync_api, object_service_handle,
service_name, *service_ver);
corosync_api->object_destroy (object_service_handle);
corosync_api->object_find_destroy (object_find_handle);
}
return (0);
}
/*
* Links default services into the executive
*/
unsigned int corosync_service_defaults_link_and_init (struct corosync_api_v1 *corosync_api)
{
unsigned int i;
hdb_handle_t object_service_handle;
char *found_service_name;
char *found_service_ver;
unsigned int found_service_ver_atoi;
hdb_handle_t object_find_handle;
-
+
corosync_api->object_create (OBJECT_PARENT_HANDLE,
&object_internal_configuration_handle,
"internal_configuration",
strlen ("internal_configuration"));
corosync_api->object_find_create (
OBJECT_PARENT_HANDLE,
"service",
strlen ("service"),
&object_find_handle);
while (corosync_api->object_find_next (
object_find_handle,
&object_service_handle) == 0) {
corosync_api->object_key_get (object_service_handle,
"name",
strlen ("name"),
(void *)&found_service_name,
NULL);
corosync_api->object_key_get (object_service_handle,
"ver",
strlen ("ver"),
(void *)&found_service_ver,
NULL);
found_service_ver_atoi = atoi (found_service_ver);
corosync_service_link_and_init (
corosync_api,
found_service_name,
found_service_ver_atoi);
}
corosync_api->object_find_destroy (object_find_handle);
if (default_services_requested (corosync_api) == 0) {
return (0);
}
for (i = 0;
i < sizeof (default_services) / sizeof (struct default_service); i++) {
corosync_service_link_and_init (
corosync_api,
default_services[i].name,
default_services[i].ver);
}
-
+
return (0);
}
diff --git a/exec/sync.c b/exec/sync.c
index ffc08521..d34ee165 100644
--- a/exec/sync.c
+++ b/exec/sync.c
@@ -1,452 +1,452 @@
/*
* Copyright (c) 2005-2006 MontaVista Software, Inc.
* Copyright (c) 2006-2007, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <corosync/corotypes.h>
#include <corosync/swab.h>
#include <corosync/totem/totempg.h>
#include <corosync/totem/totem.h>
#include <corosync/lcr/lcr_ifact.h>
#include <corosync/engine/logsys.h>
#include <corosync/ipc_gen.h>
#include "quorum.h"
#include "sync.h"
LOGSYS_DECLARE_SUBSYS ("SYNC");
#define MESSAGE_REQ_SYNC_BARRIER 0
struct barrier_data {
unsigned int nodeid;
int completed;
};
static const struct memb_ring_id *sync_ring_id;
static int (*sync_callbacks_retrieve) (int sync_id, struct sync_callbacks *callack);
static struct sync_callbacks sync_callbacks;
static int sync_processing = 0;
static void (*sync_synchronization_completed) (void);
static int sync_recovery_index = 0;
static void *sync_callback_token_handle = 0;
static struct barrier_data barrier_data_confchg[PROCESSOR_COUNT_MAX];
static size_t barrier_data_confchg_entries;
static struct barrier_data barrier_data_process[PROCESSOR_COUNT_MAX];
static int sync_barrier_send (const struct memb_ring_id *ring_id);
static int sync_start_process (enum totem_callback_token_type type,
const void *data);
static void sync_service_init (struct memb_ring_id *ring_id);
static int sync_service_process (enum totem_callback_token_type type,
const void *data);
static void sync_deliver_fn (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required);
static void sync_confchg_fn (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id);
static void sync_primary_callback_fn (
const unsigned int *view_list,
size_t view_list_entries,
int primary_designated,
const struct memb_ring_id *ring_id);
static struct totempg_group sync_group = {
.group = "sync",
.group_len = 4
};
static hdb_handle_t sync_group_handle;
struct req_exec_sync_barrier_start {
mar_req_header_t header;
struct memb_ring_id ring_id;
};
/*
* Send a barrier data structure
*/
static int sync_barrier_send (const struct memb_ring_id *ring_id)
{
struct req_exec_sync_barrier_start req_exec_sync_barrier_start;
struct iovec iovec;
int res;
req_exec_sync_barrier_start.header.size = sizeof (struct req_exec_sync_barrier_start);
req_exec_sync_barrier_start.header.id = MESSAGE_REQ_SYNC_BARRIER;
memcpy (&req_exec_sync_barrier_start.ring_id, ring_id,
sizeof (struct memb_ring_id));
iovec.iov_base = (char *)&req_exec_sync_barrier_start;
iovec.iov_len = sizeof (req_exec_sync_barrier_start);
res = totempg_groups_mcast_joined (sync_group_handle, &iovec, 1, TOTEMPG_AGREED);
return (res);
}
static void sync_start_init (const struct memb_ring_id *ring_id)
{
totempg_callback_token_create (
&sync_callback_token_handle,
TOTEM_CALLBACK_TOKEN_SENT,
0, /* don't delete after callback */
sync_start_process,
ring_id);
}
static void sync_service_init (struct memb_ring_id *ring_id)
{
sync_callbacks.sync_init ();
totempg_callback_token_destroy (&sync_callback_token_handle);
/*
* Create the token callback for the processing
*/
totempg_callback_token_create (
&sync_callback_token_handle,
TOTEM_CALLBACK_TOKEN_SENT,
0, /* don't delete after callback */
sync_service_process,
ring_id);
}
static int sync_start_process (enum totem_callback_token_type type,
const void *data)
{
int res;
const struct memb_ring_id *ring_id = data;
res = sync_barrier_send (ring_id);
if (res == 0) {
/*
* Delete the token callback for the barrier
*/
totempg_callback_token_destroy (&sync_callback_token_handle);
}
return (0);
}
static void sync_callbacks_load (void)
{
int res;
for (;;) {
res = sync_callbacks_retrieve (sync_recovery_index,
&sync_callbacks);
/*
* No more service handlers have sync callbacks at this time
` */
if (res == -1) {
sync_processing = 0;
break;
}
sync_recovery_index += 1;
if (sync_callbacks.sync_init) {
break;
}
}
}
static int sync_service_process (enum totem_callback_token_type type,
const void *data)
{
int res;
const struct memb_ring_id *ring_id = data;
/*
* If process operation not from this ring id, then ignore it and stop
* processing
*/
if (memcmp (ring_id, sync_ring_id, sizeof (struct memb_ring_id)) != 0) {
return (0);
}
/*
* If process returns 0, then its time to activate
* and start the next service's synchronization
*/
res = sync_callbacks.sync_process ();
if (res != 0) {
return (0);
}
totempg_callback_token_destroy (&sync_callback_token_handle);
sync_start_init (ring_id);
return (0);
}
int sync_register (
int (*callbacks_retrieve) (int sync_id, struct sync_callbacks *callack),
void (*synchronization_completed) (void))
{
unsigned int res;
res = totempg_groups_initialize (
&sync_group_handle,
sync_deliver_fn,
sync_confchg_fn);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR,
"Couldn't initialize groups interface.\n");
return (-1);
}
res = totempg_groups_join (
sync_group_handle,
&sync_group,
1);
if (res == -1) {
log_printf (LOGSYS_LEVEL_ERROR, "Couldn't join group.\n");
return (-1);
}
-
+
sync_callbacks_retrieve = callbacks_retrieve;
sync_synchronization_completed = synchronization_completed;
return (0);
}
static void sync_primary_callback_fn (
const unsigned int *view_list,
size_t view_list_entries,
int primary_designated,
const struct memb_ring_id *ring_id)
{
int i;
if (primary_designated) {
log_printf (LOGSYS_LEVEL_DEBUG, "This node is within the primary component and will provide service.\n");
} else {
log_printf (LOGSYS_LEVEL_DEBUG, "This node is within the non-primary component and will NOT provide any services.\n");
return;
}
/*
* Execute configuration change for synchronization service
*/
sync_processing = 1;
totempg_callback_token_destroy (&sync_callback_token_handle);
sync_recovery_index = 0;
memset (&barrier_data_confchg, 0, sizeof (barrier_data_confchg));
for (i = 0; i < view_list_entries; i++) {
barrier_data_confchg[i].nodeid = view_list[i];
barrier_data_confchg[i].completed = 0;
}
memcpy (barrier_data_process, barrier_data_confchg,
sizeof (barrier_data_confchg));
barrier_data_confchg_entries = view_list_entries;
sync_start_init (sync_ring_id);
}
static struct memb_ring_id deliver_ring_id;
static void sync_endian_convert (struct req_exec_sync_barrier_start
*req_exec_sync_barrier_start)
{
totemip_copy_endian_convert(&req_exec_sync_barrier_start->ring_id.rep,
&req_exec_sync_barrier_start->ring_id.rep);
req_exec_sync_barrier_start->ring_id.seq = swab64 (req_exec_sync_barrier_start->ring_id.seq);
}
static void sync_deliver_fn (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required)
{
struct req_exec_sync_barrier_start *req_exec_sync_barrier_start =
(struct req_exec_sync_barrier_start *)iovec[0].iov_base;
unsigned int barrier_completed;
int i;
log_printf (LOGSYS_LEVEL_DEBUG, "confchg entries %lu\n",
(unsigned long int) barrier_data_confchg_entries);
if (endian_conversion_required) {
sync_endian_convert (req_exec_sync_barrier_start);
}
barrier_completed = 1;
memcpy (&deliver_ring_id, &req_exec_sync_barrier_start->ring_id,
sizeof (struct memb_ring_id));
/*
* Is this barrier from this configuration, if not, ignore it
*/
if (memcmp (&req_exec_sync_barrier_start->ring_id, sync_ring_id,
sizeof (struct memb_ring_id)) != 0) {
return;
}
/*
* Set completion for source_addr's address
*/
for (i = 0; i < barrier_data_confchg_entries; i++) {
if (nodeid == barrier_data_process[i].nodeid) {
barrier_data_process[i].completed = 1;
log_printf (LOGSYS_LEVEL_DEBUG,
"Barrier Start Recieved From %d\n",
barrier_data_process[i].nodeid);
break;
}
}
/*
* Test if barrier is complete
*/
for (i = 0; i < barrier_data_confchg_entries; i++) {
log_printf (LOGSYS_LEVEL_DEBUG,
"Barrier completion status for nodeid %d = %d. \n",
barrier_data_process[i].nodeid,
barrier_data_process[i].completed);
if (barrier_data_process[i].completed == 0) {
barrier_completed = 0;
}
}
if (barrier_completed) {
log_printf (LOGSYS_LEVEL_DEBUG,
"Synchronization barrier completed\n");
}
/*
* This sync is complete so activate and start next service sync
*/
if (barrier_completed && sync_callbacks.sync_activate) {
sync_callbacks.sync_activate ();
log_printf (LOGSYS_LEVEL_DEBUG,
"Committing synchronization for (%s)\n",
sync_callbacks.name);
}
/*
* Start synchronization if the barrier has completed
*/
if (barrier_completed) {
memcpy (barrier_data_process, barrier_data_confchg,
sizeof (barrier_data_confchg));
sync_callbacks_load();
/*
* if sync service found, execute it
*/
if (sync_processing && sync_callbacks.sync_init) {
log_printf (LOGSYS_LEVEL_DEBUG,
"Synchronization actions starting for (%s)\n",
sync_callbacks.name);
sync_service_init (&deliver_ring_id);
}
}
return;
}
static void sync_confchg_fn (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id)
{
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;
}
sync_primary_callback_fn (
member_list,
member_list_entries,
1,
ring_id);
}
int sync_in_process (void)
{
return (sync_processing);
}
int sync_primary_designated (void)
{
return (1);
}
diff --git a/exec/tlist.h b/exec/tlist.h
index 8c57a7f6..263c8d74 100644
--- a/exec/tlist.h
+++ b/exec/tlist.h
@@ -1,262 +1,262 @@
/*
* Copyright (c) 2003-2004 MontaVista Software, Inc.
* Copyright (c) 2006-2007, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TLIST_H_DEFINED
#define TLIST_H_DEFINED
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>
#include <corosync/list.h>
#ifndef HZ
#define HZ 100 /* 10ms */
#endif
#ifndef TIMER_HANDLE
typedef void * timer_handle;
#define TIMER_HANDLE
#endif
struct timerlist {
struct list_head timer_head;
struct list_head *timer_iter;
};
struct timerlist_timer {
struct list_head list;
unsigned long long nano_from_epoch;
void (*timer_fn)(void *data);
void *data;
timer_handle handle_addr;
};
static inline void timerlist_init (struct timerlist *timerlist)
{
list_init (&timerlist->timer_head);
}
static inline unsigned long long timerlist_nano_from_epoch (void)
{
unsigned long long nano_from_epoch;
struct timeval time_from_epoch;
gettimeofday (&time_from_epoch, 0);
nano_from_epoch = ((time_from_epoch.tv_sec * 1000000000ULL) + (time_from_epoch.tv_usec * 1000ULL));
return (nano_from_epoch);
}
static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_timer *timer)
{
struct list_head *timer_list = 0;
struct timerlist_timer *timer_from_list;
int found;
for (found = 0, timer_list = timerlist->timer_head.next;
timer_list != &timerlist->timer_head;
timer_list = timer_list->next) {
timer_from_list = list_entry (timer_list,
struct timerlist_timer, list);
if (timer_from_list->nano_from_epoch > timer->nano_from_epoch) {
list_add (&timer->list, timer_list->prev);
found = 1;
break; /* for timer iteration */
}
}
if (found == 0) {
list_add (&timer->list, timerlist->timer_head.prev);
}
}
static inline int timerlist_add_absolute (struct timerlist *timerlist,
void (*timer_fn) (void *data),
void *data,
unsigned long long nano_from_epoch,
timer_handle *handle)
{
struct timerlist_timer *timer;
timer = (struct timerlist_timer *)malloc (sizeof (struct timerlist_timer));
if (timer == 0) {
errno = ENOMEM;
return (-1);
}
-
+
timer->nano_from_epoch = nano_from_epoch;
timer->data = data;
timer->timer_fn = timer_fn;
timer->handle_addr = handle;
timerlist_add (timerlist, timer);
*handle = timer;
return (0);
}
static inline int timerlist_add_duration (struct timerlist *timerlist,
void (*timer_fn) (void *data),
void *data,
unsigned long long nano_duration,
timer_handle *handle)
{
struct timerlist_timer *timer;
timer = (struct timerlist_timer *)malloc (sizeof (struct timerlist_timer));
if (timer == 0) {
errno = ENOMEM;
return (-1);
}
-
+
timer->nano_from_epoch = timerlist_nano_from_epoch() + nano_duration;
timer->data = data;
timer->timer_fn = timer_fn;
timer->handle_addr = handle;
timerlist_add (timerlist, timer);
*handle = timer;
return (0);
}
static inline void timerlist_del (struct timerlist *timerlist,
timer_handle _timer_handle)
{
struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
memset (timer->handle_addr, 0, sizeof (struct timerlist_timer *));
/*
* If the next timer after the currently expiring timer because
* timerlist_del is called from a timer handler, get to the next
* timer
*/
if (timerlist->timer_iter == &timer->list) {
timerlist->timer_iter = timerlist->timer_iter->next;
}
list_del (&timer->list);
list_init (&timer->list);
free (timer);
}
static inline unsigned long long timerlist_expire_time (struct timerlist *timerlist, timer_handle _timer_handle)
{
struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
return (timer->nano_from_epoch);
}
static inline void timerlist_pre_dispatch (struct timerlist *timerlist, timer_handle _timer_handle)
{
struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
memset (timer->handle_addr, 0, sizeof (struct timerlist_timer *));
list_del (&timer->list);
list_init (&timer->list);
}
static inline void timerlist_post_dispatch (struct timerlist *timerlist, timer_handle _timer_handle)
{
struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
free (timer);
}
/*
* returns the number of msec until the next timer will expire for use with poll
*/
static inline unsigned long long timerlist_msec_duration_to_expire (struct timerlist *timerlist)
{
struct timerlist_timer *timer_from_list;
volatile unsigned long long nano_from_epoch;
volatile unsigned long long msec_duration_to_expire;
/*
* empty list, no expire
*/
if (timerlist->timer_head.next == &timerlist->timer_head) {
return (-1);
}
-
+
timer_from_list = list_entry (timerlist->timer_head.next,
struct timerlist_timer, list);
nano_from_epoch = timerlist_nano_from_epoch();
/*
* timer at head of list is expired, zero msecs required
*/
if (timer_from_list->nano_from_epoch < nano_from_epoch) {
return (0);
}
-
+
msec_duration_to_expire = ((timer_from_list->nano_from_epoch - nano_from_epoch) / 1000000ULL) +
(1000 / HZ);
return (msec_duration_to_expire);
}
/*
* Expires any timers that should be expired
*/
static inline void timerlist_expire (struct timerlist *timerlist)
{
struct timerlist_timer *timer_from_list;
unsigned long long nano_from_epoch;
nano_from_epoch = timerlist_nano_from_epoch();
for (timerlist->timer_iter = timerlist->timer_head.next;
timerlist->timer_iter != &timerlist->timer_head;) {
timer_from_list = list_entry (timerlist->timer_iter,
struct timerlist_timer, list);
if (timer_from_list->nano_from_epoch < nano_from_epoch) {
timerlist->timer_iter = timerlist->timer_iter->next;
timerlist_pre_dispatch (timerlist, timer_from_list);
timer_from_list->timer_fn (timer_from_list->data);
timerlist_post_dispatch (timerlist, timer_from_list);
} else {
break; /* for timer iteration */
}
}
timerlist->timer_iter = 0;
}
#endif /* TLIST_H_DEFINED */
diff --git a/exec/totemconfig.h b/exec/totemconfig.h
index 718c6fb5..7169c071 100644
--- a/exec/totemconfig.h
+++ b/exec/totemconfig.h
@@ -1,61 +1,61 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2007 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.
*/
#ifndef TOTEMCONFIG_H_DEFINED
#define TOTEMCONFIG_H_DEFINED
#include <netinet/in.h>
#include <corosync/corotypes.h>
#include <corosync/list.h>
#include <corosync/totem/coropoll.h>
#include <corosync/totem/totempg.h>
#include <corosync/engine/objdb.h>
#include "totemsrp.h"
extern int totem_config_read (
struct objdb_iface_ver0 *objdb,
struct totem_config *totem_config,
const char **error_string);
-
+
extern int totem_config_validate (
struct totem_config *totem_config,
const char **error_string);
int totem_config_keyread (
struct objdb_iface_ver0 *objdb,
struct totem_config *totem_config,
const char **error_string);
#endif /* TOTEMCONFIG_H_DEFINED */
diff --git a/exec/totemnet.c b/exec/totemnet.c
index 6c83c6c0..bd9ab3d9 100644
--- a/exec/totemnet.c
+++ b/exec/totemnet.c
@@ -1,1502 +1,1502 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <corosync/queue.h>
#include <corosync/sq.h>
#include <corosync/list.h>
#include <corosync/hdb.h>
#include <corosync/swab.h>
#include <corosync/totem/coropoll.h>
#include "totemnet.h"
#include "wthread.h"
#include "crypto.h"
-#define MCAST_SOCKET_BUFFER_SIZE (TRANSMITS_ALLOWED * FRAME_SIZE_MAX)
+#define MCAST_SOCKET_BUFFER_SIZE (TRANSMITS_ALLOWED * FRAME_SIZE_MAX)
-#define NETIF_STATE_REPORT_UP 1
+#define NETIF_STATE_REPORT_UP 1
#define NETIF_STATE_REPORT_DOWN 2
#define BIND_STATE_UNBOUND 0
#define BIND_STATE_REGULAR 1
#define BIND_STATE_LOOPBACK 2
#define HMAC_HASH_SIZE 20
struct security_header {
unsigned char hash_digest[HMAC_HASH_SIZE]; /* The hash *MUST* be first in the data structure */
unsigned char salt[16]; /* random number */
char msg[0];
} __attribute__((packed));
struct totemnet_mcast_thread_state {
unsigned char iobuf[FRAME_SIZE_MAX];
prng_state prng_state;
};
struct totemnet_socket {
int mcast_recv;
int mcast_send;
int token;
};
struct totemnet_instance {
hmac_state totemnet_hmac_state;
prng_state totemnet_prng_state;
unsigned char totemnet_private_key[1024];
unsigned int totemnet_private_key_len;
hdb_handle_t totemnet_poll_handle;
struct totem_interface *totem_interface;
int netif_state_report;
int netif_bind_state;
struct worker_thread_group worker_thread_group;
void *context;
void (*totemnet_deliver_fn) (
void *context,
const void *msg,
size_t msg_len);
void (*totemnet_iface_change_fn) (
void *context,
const struct totem_ip_address *iface_address);
/*
* Function and data used to log messages
*/
int totemnet_log_level_security;
int totemnet_log_level_error;
int totemnet_log_level_warning;
int totemnet_log_level_notice;
int totemnet_log_level_debug;
int totemnet_subsys_id;
void (*totemnet_log_printf) (int subsys,
const char *function,
const char *file,
int line, unsigned int level,
const char *format,
...)__attribute__((format(printf, 6, 7)));
hdb_handle_t handle;
char iov_buffer[FRAME_SIZE_MAX];
char iov_buffer_flush[FRAME_SIZE_MAX];
struct iovec totemnet_iov_recv;
struct iovec totemnet_iov_recv_flush;
struct totemnet_socket totemnet_sockets;
struct totem_ip_address mcast_address;
int stats_sent;
int stats_recv;
int stats_delv;
int stats_remcasts;
int stats_orf_token;
struct timeval stats_tv_start;
struct totem_ip_address my_id;
int firstrun;
poll_timer_handle timer_netif_check_timeout;
unsigned int my_memb_entries;
int flushing;
struct totem_config *totem_config;
struct totem_ip_address token_target;
};
struct work_item {
struct iovec iovec[20];
unsigned int iov_len;
struct totemnet_instance *instance;
};
static void netif_down_check (struct totemnet_instance *instance);
static int totemnet_build_sockets (
struct totemnet_instance *instance,
struct totem_ip_address *bindnet_address,
struct totem_ip_address *mcastaddress,
struct totemnet_socket *sockets,
struct totem_ip_address *bound_to);
static struct totem_ip_address localhost;
DECLARE_HDB_DATABASE (totemnet_instance_database);
static void totemnet_instance_initialize (struct totemnet_instance *instance)
{
memset (instance, 0, sizeof (struct totemnet_instance));
instance->netif_state_report = NETIF_STATE_REPORT_UP | NETIF_STATE_REPORT_DOWN;
instance->totemnet_iov_recv.iov_base = instance->iov_buffer;
instance->totemnet_iov_recv.iov_len = FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
instance->totemnet_iov_recv_flush.iov_base = instance->iov_buffer_flush;
instance->totemnet_iov_recv_flush.iov_len = FRAME_SIZE_MAX; //sizeof (instance->iov_buffer);
/*
* There is always atleast 1 processor
*/
instance->my_memb_entries = 1;
}
#define log_printf(level, format, args...) \
do { \
instance->totemnet_log_printf (instance->totemnet_subsys_id, \
__FUNCTION__, __FILE__, __LINE__, \
level, (const char *)format, ##args); \
} while (0);
static int authenticate_and_decrypt (
struct totemnet_instance *instance,
struct iovec *iov)
{
unsigned char keys[48];
struct security_header *header = iov[0].iov_base;
prng_state keygen_prng_state;
prng_state stream_prng_state;
unsigned char *hmac_key = &keys[32];
unsigned char *cipher_key = &keys[16];
unsigned char *initial_vector = &keys[0];
unsigned char digest_comparison[HMAC_HASH_SIZE];
unsigned long len;
/*
* Generate MAC, CIPHER, IV keys from private key
*/
memset (keys, 0, sizeof (keys));
sober128_start (&keygen_prng_state);
sober128_add_entropy (instance->totemnet_private_key,
- instance->totemnet_private_key_len, &keygen_prng_state);
+ instance->totemnet_private_key_len, &keygen_prng_state);
sober128_add_entropy (header->salt, sizeof (header->salt), &keygen_prng_state);
sober128_read (keys, sizeof (keys), &keygen_prng_state);
/*
* Setup stream cipher
*/
sober128_start (&stream_prng_state);
- sober128_add_entropy (cipher_key, 16, &stream_prng_state);
- sober128_add_entropy (initial_vector, 16, &stream_prng_state);
+ sober128_add_entropy (cipher_key, 16, &stream_prng_state);
+ sober128_add_entropy (initial_vector, 16, &stream_prng_state);
/*
* Authenticate contents of message
*/
hmac_init (&instance->totemnet_hmac_state, DIGEST_SHA1, hmac_key, 16);
- hmac_process (&instance->totemnet_hmac_state,
+ hmac_process (&instance->totemnet_hmac_state,
(unsigned char *)iov->iov_base + HMAC_HASH_SIZE,
iov->iov_len - HMAC_HASH_SIZE);
len = hash_descriptor[DIGEST_SHA1]->hashsize;
assert (HMAC_HASH_SIZE >= len);
hmac_done (&instance->totemnet_hmac_state, digest_comparison, &len);
if (memcmp (digest_comparison, header->hash_digest, len) != 0) {
log_printf (instance->totemnet_log_level_security, "Received message has invalid digest... ignoring.\n");
return (-1);
}
-
+
/*
* Decrypt the contents of the message with the cipher key
*/
sober128_read ((unsigned char*)iov->iov_base +
sizeof (struct security_header),
iov->iov_len - sizeof (struct security_header),
&stream_prng_state);
return (0);
}
static void encrypt_and_sign_worker (
struct totemnet_instance *instance,
unsigned char *buf,
size_t *buf_len,
const struct iovec *iovec,
size_t iov_len,
prng_state *prng_state_in)
{
int i;
unsigned char *addr;
unsigned char keys[48];
struct security_header *header;
unsigned char *hmac_key = &keys[32];
unsigned char *cipher_key = &keys[16];
unsigned char *initial_vector = &keys[0];
unsigned long len;
size_t outlen = 0;
hmac_state hmac_st;
prng_state keygen_prng_state;
prng_state stream_prng_state;
header = (struct security_header *)buf;
addr = buf + sizeof (struct security_header);
memset (keys, 0, sizeof (keys));
memset (header->salt, 0, sizeof (header->salt));
/*
* Generate MAC, CIPHER, IV keys from private key
*/
sober128_read (header->salt, sizeof (header->salt), prng_state_in);
sober128_start (&keygen_prng_state);
sober128_add_entropy (instance->totemnet_private_key,
instance->totemnet_private_key_len,
- &keygen_prng_state);
+ &keygen_prng_state);
sober128_add_entropy (header->salt, sizeof (header->salt),
&keygen_prng_state);
sober128_read (keys, sizeof (keys), &keygen_prng_state);
/*
* Setup stream cipher
*/
sober128_start (&stream_prng_state);
- sober128_add_entropy (cipher_key, 16, &stream_prng_state);
- sober128_add_entropy (initial_vector, 16, &stream_prng_state);
+ sober128_add_entropy (cipher_key, 16, &stream_prng_state);
+ sober128_add_entropy (initial_vector, 16, &stream_prng_state);
outlen = sizeof (struct security_header);
/*
* Copy remainder of message, then encrypt it
*/
for (i = 1; i < iov_len; i++) {
memcpy (addr, iovec[i].iov_base, iovec[i].iov_len);
addr += iovec[i].iov_len;
outlen += iovec[i].iov_len;
}
/*
* Encrypt message by XORing stream cipher data
*/
sober128_read (buf + sizeof (struct security_header),
outlen - sizeof (struct security_header),
&stream_prng_state);
memset (&hmac_st, 0, sizeof (hmac_st));
/*
* Sign the contents of the message with the hmac key and store signature in message
*/
hmac_init (&hmac_st, DIGEST_SHA1, hmac_key, 16);
- hmac_process (&hmac_st,
+ hmac_process (&hmac_st,
buf + HMAC_HASH_SIZE,
outlen - HMAC_HASH_SIZE);
len = hash_descriptor[DIGEST_SHA1]->hashsize;
hmac_done (&hmac_st, header->hash_digest, &len);
*buf_len = outlen;
}
static inline void ucast_sendmsg (
struct totemnet_instance *instance,
struct totem_ip_address *system_to,
const struct iovec *iovec_in,
size_t iov_len_in)
{
struct msghdr msg_ucast;
int res = 0;
size_t buf_len;
unsigned char sheader[sizeof (struct security_header)];
unsigned char encrypt_data[FRAME_SIZE_MAX];
struct iovec iovec_encrypt[20];
const struct iovec *iovec_sendmsg;
struct sockaddr_storage sockaddr;
unsigned int iov_len;
int addrlen;
if (instance->totem_config->secauth == 1) {
iovec_encrypt[0].iov_base = sheader;
iovec_encrypt[0].iov_len = sizeof (struct security_header);
memcpy (&iovec_encrypt[1], &iovec_in[0],
sizeof (struct iovec) * iov_len_in);
/*
* Encrypt and digest the message
*/
encrypt_and_sign_worker (
instance,
encrypt_data,
&buf_len,
iovec_encrypt,
iov_len_in + 1,
&instance->totemnet_prng_state);
iovec_encrypt[0].iov_base = encrypt_data;
iovec_encrypt[0].iov_len = buf_len;
iovec_sendmsg = &iovec_encrypt[0];
iov_len = 1;
} else {
iovec_sendmsg = iovec_in;
iov_len = iov_len_in;
}
/*
* Build unicast message
*/
totemip_totemip_to_sockaddr_convert(system_to,
instance->totem_interface->ip_port, &sockaddr, &addrlen);
msg_ucast.msg_name = &sockaddr;
msg_ucast.msg_namelen = addrlen;
msg_ucast.msg_iov = (void *) iovec_sendmsg;
msg_ucast.msg_iovlen = iov_len;
msg_ucast.msg_control = 0;
msg_ucast.msg_controllen = 0;
msg_ucast.msg_flags = 0;
/*
* Transmit multicast message
* An error here is recovered by totemsrp
*/
res = sendmsg (instance->totemnet_sockets.mcast_send, &msg_ucast,
MSG_NOSIGNAL);
}
static inline void mcast_sendmsg (
struct totemnet_instance *instance,
const struct iovec *iovec_in,
size_t iov_len_in)
{
struct msghdr msg_mcast;
int res = 0;
size_t buf_len;
unsigned char sheader[sizeof (struct security_header)];
unsigned char encrypt_data[FRAME_SIZE_MAX];
struct iovec iovec_encrypt[20];
const struct iovec *iovec_sendmsg;
struct sockaddr_storage sockaddr;
unsigned int iov_len;
int addrlen;
if (instance->totem_config->secauth == 1) {
iovec_encrypt[0].iov_base = sheader;
iovec_encrypt[0].iov_len = sizeof (struct security_header);
memcpy (&iovec_encrypt[1], &iovec_in[0],
sizeof (struct iovec) * iov_len_in);
/*
* Encrypt and digest the message
*/
encrypt_and_sign_worker (
instance,
encrypt_data,
&buf_len,
iovec_encrypt,
iov_len_in + 1,
&instance->totemnet_prng_state);
iovec_encrypt[0].iov_base = encrypt_data;
iovec_encrypt[0].iov_len = buf_len;
iovec_sendmsg = &iovec_encrypt[0];
iov_len = 1;
} else {
iovec_sendmsg = iovec_in;
iov_len = iov_len_in;
}
/*
* Build multicast message
*/
totemip_totemip_to_sockaddr_convert(&instance->mcast_address,
instance->totem_interface->ip_port, &sockaddr, &addrlen);
msg_mcast.msg_name = &sockaddr;
msg_mcast.msg_namelen = addrlen;
msg_mcast.msg_iov = (void *) iovec_sendmsg;
msg_mcast.msg_iovlen = iov_len;
msg_mcast.msg_control = 0;
msg_mcast.msg_controllen = 0;
msg_mcast.msg_flags = 0;
/*
* Transmit multicast message
* An error here is recovered by totemsrp
*/
res = sendmsg (instance->totemnet_sockets.mcast_send, &msg_mcast,
MSG_NOSIGNAL);
}
static void totemnet_mcast_thread_state_constructor (
void *totemnet_mcast_thread_state_in)
{
struct totemnet_mcast_thread_state *totemnet_mcast_thread_state =
(struct totemnet_mcast_thread_state *)totemnet_mcast_thread_state_in;
memset (totemnet_mcast_thread_state, 0,
sizeof (totemnet_mcast_thread_state));
rng_make_prng (128, PRNG_SOBER,
&totemnet_mcast_thread_state->prng_state, NULL);
}
static void totemnet_mcast_worker_fn (void *thread_state, void *work_item_in)
{
struct work_item *work_item = (struct work_item *)work_item_in;
struct totemnet_mcast_thread_state *totemnet_mcast_thread_state =
(struct totemnet_mcast_thread_state *)thread_state;
struct totemnet_instance *instance = work_item->instance;
struct msghdr msg_mcast;
unsigned char sheader[sizeof (struct security_header)];
int res = 0;
size_t buf_len;
struct iovec iovec_encrypted;
struct iovec *iovec_sendmsg;
struct sockaddr_storage sockaddr;
unsigned int iovs;
int addrlen;
if (instance->totem_config->secauth == 1) {
memmove (&work_item->iovec[1], &work_item->iovec[0],
work_item->iov_len * sizeof (struct iovec));
work_item->iovec[0].iov_base = sheader;
work_item->iovec[0].iov_len = sizeof (struct security_header);
/*
* Encrypt and digest the message
*/
encrypt_and_sign_worker (
instance,
totemnet_mcast_thread_state->iobuf, &buf_len,
work_item->iovec, work_item->iov_len + 1,
&totemnet_mcast_thread_state->prng_state);
iovec_sendmsg = &iovec_encrypted;
iovec_sendmsg->iov_base = totemnet_mcast_thread_state->iobuf;
iovec_sendmsg->iov_len = buf_len;
iovs = 1;
} else {
iovec_sendmsg = work_item->iovec;
iovs = work_item->iov_len;
}
totemip_totemip_to_sockaddr_convert(&instance->mcast_address,
instance->totem_interface->ip_port, &sockaddr, &addrlen);
msg_mcast.msg_name = &sockaddr;
msg_mcast.msg_namelen = addrlen;
msg_mcast.msg_iov = iovec_sendmsg;
msg_mcast.msg_iovlen = iovs;
msg_mcast.msg_control = 0;
msg_mcast.msg_controllen = 0;
msg_mcast.msg_flags = 0;
/*
* Transmit multicast message
* An error here is recovered by totemnet
*/
res = sendmsg (instance->totemnet_sockets.mcast_send, &msg_mcast,
MSG_NOSIGNAL);
if (res > 0) {
instance->stats_sent += res;
}
}
int totemnet_finalize (
hdb_handle_t handle)
{
struct totemnet_instance *instance;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
worker_thread_group_exit (&instance->worker_thread_group);
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
/*
* Only designed to work with a message with one iov
*/
static int net_deliver_fn (
hdb_handle_t handle,
int fd,
int revents,
void *data)
{
struct totemnet_instance *instance = (struct totemnet_instance *)data;
struct msghdr msg_recv;
struct iovec *iovec;
struct security_header *security_header;
struct sockaddr_storage system_from;
int bytes_received;
int res = 0;
unsigned char *msg_offset;
unsigned int size_delv;
if (instance->flushing == 1) {
iovec = &instance->totemnet_iov_recv_flush;
} else {
iovec = &instance->totemnet_iov_recv;
}
/*
* Receive datagram
*/
msg_recv.msg_name = &system_from;
msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
msg_recv.msg_iov = iovec;
msg_recv.msg_iovlen = 1;
msg_recv.msg_control = 0;
msg_recv.msg_controllen = 0;
msg_recv.msg_flags = 0;
bytes_received = recvmsg (fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT);
if (bytes_received == -1) {
return (0);
} else {
instance->stats_recv += bytes_received;
}
if ((instance->totem_config->secauth == 1) &&
(bytes_received < sizeof (struct security_header))) {
log_printf (instance->totemnet_log_level_security, "Received message is too short... ignoring %d.\n", bytes_received);
return (0);
}
security_header = (struct security_header *)iovec->iov_base;
iovec->iov_len = bytes_received;
if (instance->totem_config->secauth == 1) {
/*
* Authenticate and if authenticated, decrypt datagram
*/
res = authenticate_and_decrypt (instance, iovec);
if (res == -1) {
log_printf (instance->totemnet_log_level_security,
"Invalid packet data\n");
iovec->iov_len = FRAME_SIZE_MAX;
return 0;
}
msg_offset = (unsigned char *)iovec->iov_base +
sizeof (struct security_header);
size_delv = bytes_received - sizeof (struct security_header);
} else {
msg_offset = iovec->iov_base;
size_delv = bytes_received;
}
/*
* Handle incoming message
*/
instance->totemnet_deliver_fn (
instance->context,
msg_offset,
size_delv);
-
+
iovec->iov_len = FRAME_SIZE_MAX;
return (0);
}
static int netif_determine (
struct totemnet_instance *instance,
struct totem_ip_address *bindnet,
struct totem_ip_address *bound_to,
int *interface_up,
int *interface_num)
{
int res;
res = totemip_iface_check (bindnet, bound_to,
interface_up, interface_num,
+ 0); // TODO andrew can address this instance->totem_config->clear_node_high_bit);
return (res);
}
-
+
/*
* If the interface is up, the sockets for totem are built. If the interface is down
* this function is requeued in the timer list to retry building the sockets later.
*/
static void timer_function_netif_check_timeout (
void *data)
{
struct totemnet_instance *instance = (struct totemnet_instance *)data;
int res;
int interface_up;
int interface_num;
struct totem_ip_address *bind_address;
/*
* Build sockets for every interface
*/
netif_determine (instance,
&instance->totem_interface->bindnet,
&instance->totem_interface->boundto,
&interface_up, &interface_num);
/*
* If the network interface isn't back up and we are already
* in loopback mode, add timer to check again and return
*/
if ((instance->netif_bind_state == BIND_STATE_LOOPBACK &&
interface_up == 0) ||
(instance->my_memb_entries == 1 &&
instance->netif_bind_state == BIND_STATE_REGULAR &&
interface_up == 1)) {
poll_timer_add (instance->totemnet_poll_handle,
instance->totem_config->downcheck_timeout,
(void *)instance,
timer_function_netif_check_timeout,
&instance->timer_netif_check_timeout);
/*
* Add a timer to check for a downed regular interface
*/
return;
}
if (instance->totemnet_sockets.mcast_recv > 0) {
close (instance->totemnet_sockets.mcast_recv);
poll_dispatch_delete (instance->totemnet_poll_handle,
instance->totemnet_sockets.mcast_recv);
}
if (instance->totemnet_sockets.mcast_send > 0) {
close (instance->totemnet_sockets.mcast_send);
}
if (instance->totemnet_sockets.token > 0) {
close (instance->totemnet_sockets.token);
poll_dispatch_delete (instance->totemnet_poll_handle,
instance->totemnet_sockets.token);
}
if (interface_up == 0) {
/*
* Interface is not up
*/
instance->netif_bind_state = BIND_STATE_LOOPBACK;
bind_address = &localhost;
/*
* Add a timer to retry building interfaces and request memb_gather_enter
*/
poll_timer_add (instance->totemnet_poll_handle,
instance->totem_config->downcheck_timeout,
(void *)instance,
timer_function_netif_check_timeout,
&instance->timer_netif_check_timeout);
} else {
/*
* Interface is up
*/
instance->netif_bind_state = BIND_STATE_REGULAR;
bind_address = &instance->totem_interface->bindnet;
}
/*
* Create and bind the multicast and unicast sockets
*/
res = totemnet_build_sockets (instance,
&instance->mcast_address,
bind_address,
&instance->totemnet_sockets,
&instance->totem_interface->boundto);
poll_dispatch_add (
instance->totemnet_poll_handle,
instance->totemnet_sockets.mcast_recv,
POLLIN, instance, net_deliver_fn);
poll_dispatch_add (
instance->totemnet_poll_handle,
instance->totemnet_sockets.token,
POLLIN, instance, net_deliver_fn);
totemip_copy (&instance->my_id, &instance->totem_interface->boundto);
/*
* This reports changes in the interface to the user and totemsrp
*/
if (instance->netif_bind_state == BIND_STATE_REGULAR) {
if (instance->netif_state_report & NETIF_STATE_REPORT_UP) {
log_printf (instance->totemnet_log_level_notice,
"The network interface [%s] is now up.\n",
totemip_print (&instance->totem_interface->boundto));
instance->netif_state_report = NETIF_STATE_REPORT_DOWN;
instance->totemnet_iface_change_fn (instance->context, &instance->my_id);
}
/*
* Add a timer to check for interface going down in single membership
*/
if (instance->my_memb_entries == 1) {
poll_timer_add (instance->totemnet_poll_handle,
instance->totem_config->downcheck_timeout,
(void *)instance,
timer_function_netif_check_timeout,
&instance->timer_netif_check_timeout);
}
- } else {
+ } else {
if (instance->netif_state_report & NETIF_STATE_REPORT_DOWN) {
log_printf (instance->totemnet_log_level_notice,
"The network interface is down.\n");
instance->totemnet_iface_change_fn (instance->context, &instance->my_id);
}
instance->netif_state_report = NETIF_STATE_REPORT_UP;
}
}
/*
* Check if an interface is down and reconfigure
* totemnet waiting for it to come back up
*/
static void netif_down_check (struct totemnet_instance *instance)
{
timer_function_netif_check_timeout (instance);
}
/* Set the socket priority to INTERACTIVE to ensure
that our messages don't get queued behind anything else */
static void totemnet_traffic_control_set(struct totemnet_instance *instance, int sock)
{
#ifdef SO_PRIORITY
int prio = 6; /* TC_PRIO_INTERACTIVE */
if (setsockopt(sock, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(int)))
log_printf (instance->totemnet_log_level_warning, "Could not set traffic priority. (%s)\n", strerror (errno));
#endif
}
static int totemnet_build_sockets_ip (
struct totemnet_instance *instance,
struct totem_ip_address *mcast_address,
struct totem_ip_address *bindnet_address,
struct totemnet_socket *sockets,
struct totem_ip_address *bound_to,
int interface_num)
{
struct sockaddr_storage sockaddr;
struct ipv6_mreq mreq6;
struct ip_mreq mreq;
struct sockaddr_storage mcast_ss, boundto_ss;
struct sockaddr_in6 *mcast_sin6 = (struct sockaddr_in6 *)&mcast_ss;
struct sockaddr_in *mcast_sin = (struct sockaddr_in *)&mcast_ss;
struct sockaddr_in *boundto_sin = (struct sockaddr_in *)&boundto_ss;
unsigned int sendbuf_size;
unsigned int recvbuf_size;
unsigned int optlen = sizeof (sendbuf_size);
int addrlen;
int res;
int flag;
-
+
/*
* Create multicast recv socket
*/
sockets->mcast_recv = socket (bindnet_address->family, SOCK_DGRAM, 0);
if (sockets->mcast_recv == -1) {
perror ("socket");
return (-1);
}
totemip_nosigpipe (sockets->mcast_recv);
res = fcntl (sockets->mcast_recv, F_SETFL, O_NONBLOCK);
if (res == -1) {
log_printf (instance->totemnet_log_level_warning, "Could not set non-blocking operation on multicast socket: %s\n", strerror (errno));
return (-1);
}
- /*
+ /*
* Force reuse
*/
flag = 1;
- if ( setsockopt(sockets->mcast_recv, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
+ if ( setsockopt(sockets->mcast_recv, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
perror("setsockopt reuseaddr");
return (-1);
}
/*
* Bind to multicast socket used for multicast receives
*/
totemip_totemip_to_sockaddr_convert(mcast_address,
instance->totem_interface->ip_port, &sockaddr, &addrlen);
res = bind (sockets->mcast_recv, (struct sockaddr *)&sockaddr, addrlen);
if (res == -1) {
perror ("bind mcast recv socket failed");
return (-1);
}
/*
* Setup mcast send socket
*/
sockets->mcast_send = socket (bindnet_address->family, SOCK_DGRAM, 0);
if (sockets->mcast_send == -1) {
perror ("socket");
return (-1);
}
totemip_nosigpipe (sockets->mcast_send);
res = fcntl (sockets->mcast_send, F_SETFL, O_NONBLOCK);
if (res == -1) {
log_printf (instance->totemnet_log_level_warning, "Could not set non-blocking operation on multicast socket: %s\n", strerror (errno));
return (-1);
}
- /*
+ /*
* Force reuse
*/
flag = 1;
- if ( setsockopt(sockets->mcast_send, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
+ if ( setsockopt(sockets->mcast_send, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
perror("setsockopt reuseaddr");
return (-1);
}
totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port - 1,
&sockaddr, &addrlen);
res = bind (sockets->mcast_send, (struct sockaddr *)&sockaddr, addrlen);
if (res == -1) {
perror ("bind mcast send socket failed");
return (-1);
}
/*
* Setup unicast socket
*/
sockets->token = socket (bindnet_address->family, SOCK_DGRAM, 0);
if (sockets->token == -1) {
perror ("socket2");
return (-1);
}
totemip_nosigpipe (sockets->token);
res = fcntl (sockets->token, F_SETFL, O_NONBLOCK);
if (res == -1) {
log_printf (instance->totemnet_log_level_warning, "Could not set non-blocking operation on token socket: %s\n", strerror (errno));
return (-1);
}
- /*
+ /*
* Force reuse
*/
flag = 1;
- if ( setsockopt(sockets->token, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
+ if ( setsockopt(sockets->token, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof (flag)) < 0) {
perror("setsockopt reuseaddr");
return (-1);
}
/*
* Bind to unicast socket used for token send/receives
* This has the side effect of binding to the correct interface
*/
totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &sockaddr, &addrlen);
res = bind (sockets->token, (struct sockaddr *)&sockaddr, addrlen);
if (res == -1) {
perror ("bind token socket failed");
return (-1);
}
recvbuf_size = MCAST_SOCKET_BUFFER_SIZE;
sendbuf_size = MCAST_SOCKET_BUFFER_SIZE;
/*
* Set buffer sizes to avoid overruns
*/
res = setsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, optlen);
res = setsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, optlen);
res = getsockopt (sockets->mcast_recv, SOL_SOCKET, SO_RCVBUF, &recvbuf_size, &optlen);
if (res == 0) {
log_printf (instance->totemnet_log_level_notice,
"Receive multicast socket recv buffer size (%d bytes).\n", recvbuf_size);
}
res = getsockopt (sockets->mcast_send, SOL_SOCKET, SO_SNDBUF, &sendbuf_size, &optlen);
if (res == 0) {
log_printf (instance->totemnet_log_level_notice,
"Transmit multicast socket send buffer size (%d bytes).\n", sendbuf_size);
}
/*
* Join group membership on socket
*/
totemip_totemip_to_sockaddr_convert(mcast_address, instance->totem_interface->ip_port, &mcast_ss, &addrlen);
totemip_totemip_to_sockaddr_convert(bound_to, instance->totem_interface->ip_port, &boundto_ss, &addrlen);
switch ( bindnet_address->family ) {
case AF_INET:
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = mcast_sin->sin_addr.s_addr;
mreq.imr_interface.s_addr = boundto_sin->sin_addr.s_addr;
res = setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof (mreq));
if (res == -1) {
perror ("join ipv4 multicast group failed");
return (-1);
}
break;
case AF_INET6:
memset(&mreq6, 0, sizeof(mreq6));
memcpy(&mreq6.ipv6mr_multiaddr, &mcast_sin6->sin6_addr, sizeof(struct in6_addr));
mreq6.ipv6mr_interface = interface_num;
res = setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_JOIN_GROUP,
&mreq6, sizeof (mreq6));
if (res == -1) {
perror ("join ipv6 multicast group failed");
return (-1);
}
break;
}
-
+
/*
* Turn on multicast loopback
*/
flag = 1;
switch ( bindnet_address->family ) {
case AF_INET:
res = setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_LOOP,
&flag, sizeof (flag));
break;
case AF_INET6:
res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&flag, sizeof (flag));
}
if (res == -1) {
perror ("turn off loopback");
return (-1);
}
/*
* Set multicast packets TTL
*/
if ( bindnet_address->family == AF_INET6 )
{
flag = 255;
res = setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
&flag, sizeof (flag));
if (res == -1) {
perror ("setp mcast hops");
return (-1);
}
}
/*
* Bind to a specific interface for multicast send and receive
*/
switch ( bindnet_address->family ) {
case AF_INET:
if (setsockopt (sockets->mcast_send, IPPROTO_IP, IP_MULTICAST_IF,
&boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
perror ("cannot select interface");
return (-1);
}
if (setsockopt (sockets->mcast_recv, IPPROTO_IP, IP_MULTICAST_IF,
&boundto_sin->sin_addr, sizeof (boundto_sin->sin_addr)) < 0) {
perror ("cannot select interface");
return (-1);
}
break;
case AF_INET6:
if (setsockopt (sockets->mcast_send, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&interface_num, sizeof (interface_num)) < 0) {
perror ("cannot select interface");
return (-1);
}
if (setsockopt (sockets->mcast_recv, IPPROTO_IPV6, IPV6_MULTICAST_IF,
&interface_num, sizeof (interface_num)) < 0) {
perror ("cannot select interface");
return (-1);
}
break;
}
-
+
return 0;
}
static int totemnet_build_sockets (
struct totemnet_instance *instance,
struct totem_ip_address *mcast_address,
struct totem_ip_address *bindnet_address,
struct totemnet_socket *sockets,
struct totem_ip_address *bound_to)
{
int interface_num;
int interface_up;
int res;
/*
* Determine the ip address bound to and the interface name
*/
res = netif_determine (instance,
bindnet_address,
bound_to,
&interface_up,
&interface_num);
if (res == -1) {
return (-1);
}
totemip_copy(&instance->my_id, bound_to);
res = totemnet_build_sockets_ip (instance, mcast_address,
bindnet_address, sockets, bound_to, interface_num);
/* We only send out of the token socket */
totemnet_traffic_control_set(instance, sockets->token);
return res;
}
-
+
/*
* Totem Network interface - also does encryption/decryption
* depends on poll abstraction, POSIX, IPV4
*/
/*
* Create an instance
*/
int totemnet_initialize (
hdb_handle_t poll_handle,
hdb_handle_t *handle,
struct totem_config *totem_config,
int interface_no,
void *context,
void (*deliver_fn) (
void *context,
const void *msg,
size_t msg_len),
void (*iface_change_fn) (
void *context,
const struct totem_ip_address *iface_address))
{
struct totemnet_instance *instance;
unsigned int res;
res = hdb_handle_create (&totemnet_instance_database,
sizeof (struct totemnet_instance), handle);
if (res != 0) {
goto error_exit;
}
res = hdb_handle_get (&totemnet_instance_database, *handle,
(void *)&instance);
if (res != 0) {
goto error_destroy;
}
totemnet_instance_initialize (instance);
instance->totem_config = totem_config;
/*
* Configure logging
*/
instance->totemnet_log_level_security = 1; //totem_config->totem_logging_configuration.log_level_security;
instance->totemnet_log_level_error = totem_config->totem_logging_configuration.log_level_error;
instance->totemnet_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
instance->totemnet_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
instance->totemnet_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
instance->totemnet_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
instance->totemnet_log_printf = totem_config->totem_logging_configuration.log_printf;
/*
* Initialize random number generator for later use to generate salt
*/
memcpy (instance->totemnet_private_key, totem_config->private_key,
totem_config->private_key_len);
instance->totemnet_private_key_len = totem_config->private_key_len;
rng_make_prng (128, PRNG_SOBER, &instance->totemnet_prng_state, NULL);
/*
* Initialize local variables for totemnet
*/
instance->totem_interface = &totem_config->interfaces[interface_no];
totemip_copy (&instance->mcast_address, &instance->totem_interface->mcast_addr);
memset (instance->iov_buffer, 0, FRAME_SIZE_MAX);
/*
* If threaded send requested, initialize thread group data structure
*/
if (totem_config->threads) {
worker_thread_group_init (
&instance->worker_thread_group,
totem_config->threads, 128,
sizeof (struct work_item),
sizeof (struct totemnet_mcast_thread_state),
totemnet_mcast_thread_state_constructor,
totemnet_mcast_worker_fn);
}
instance->totemnet_poll_handle = poll_handle;
instance->totem_interface->bindnet.nodeid = instance->totem_config->node_id;
instance->context = context;
instance->totemnet_deliver_fn = deliver_fn;
instance->totemnet_iface_change_fn = iface_change_fn;
instance->handle = *handle;
rng_make_prng (128, PRNG_SOBER, &instance->totemnet_prng_state, NULL);
totemip_localhost (instance->mcast_address.family, &localhost);
netif_down_check (instance);
error_exit:
hdb_handle_put (&totemnet_instance_database, *handle);
return (0);
error_destroy:
hdb_handle_destroy (&totemnet_instance_database, *handle);
return (-1);
}
int totemnet_processor_count_set (
hdb_handle_t handle,
int processor_count)
{
struct totemnet_instance *instance;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
instance->my_memb_entries = processor_count;
poll_timer_delete (instance->totemnet_poll_handle,
instance->timer_netif_check_timeout);
if (processor_count == 1) {
poll_timer_add (instance->totemnet_poll_handle,
instance->totem_config->downcheck_timeout,
(void *)instance,
timer_function_netif_check_timeout,
&instance->timer_netif_check_timeout);
}
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
int totemnet_recv_flush (hdb_handle_t handle)
{
struct totemnet_instance *instance;
struct pollfd ufd;
int nfds;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
instance->flushing = 1;
do {
ufd.fd = instance->totemnet_sockets.mcast_recv;
ufd.events = POLLIN;
nfds = poll (&ufd, 1, 0);
if (nfds == 1 && ufd.revents & POLLIN) {
net_deliver_fn (0, instance->totemnet_sockets.mcast_recv,
ufd.revents, instance);
}
} while (nfds == 1);
instance->flushing = 0;
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
int totemnet_send_flush (hdb_handle_t handle)
{
struct totemnet_instance *instance;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
worker_thread_group_wait (&instance->worker_thread_group);
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
int totemnet_token_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totemnet_instance *instance;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
ucast_sendmsg (instance, &instance->token_target, iovec, iov_len);
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
int totemnet_mcast_flush_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totemnet_instance *instance;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
mcast_sendmsg (instance, iovec, iov_len);
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
int totemnet_mcast_noflush_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totemnet_instance *instance;
struct work_item work_item;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
if (instance->totem_config->threads) {
memcpy (&work_item.iovec[0], iovec, iov_len * sizeof (struct iovec));
work_item.iov_len = iov_len;
work_item.instance = instance;
worker_thread_group_work_add (&instance->worker_thread_group,
- &work_item);
+ &work_item);
} else {
mcast_sendmsg (instance, iovec, iov_len);
}
-
+
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
extern int totemnet_iface_check (hdb_handle_t handle)
{
struct totemnet_instance *instance;
int res = 0;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
timer_function_netif_check_timeout (instance);
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
extern void totemnet_net_mtu_adjust (struct totem_config *totem_config)
{
#define UDPIP_HEADER_SIZE (20 + 8) /* 20 bytes for ip 8 bytes for udp */
if (totem_config->secauth == 1) {
totem_config->net_mtu -= sizeof (struct security_header) +
UDPIP_HEADER_SIZE;
} else {
totem_config->net_mtu -= UDPIP_HEADER_SIZE;
}
}
const char *totemnet_iface_print (hdb_handle_t handle) {
struct totemnet_instance *instance;
int res = 0;
const char *ret_char;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
ret_char = "Invalid totemnet handle";
goto error_exit;
}
-
+
ret_char = totemip_print (&instance->my_id);
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (ret_char);
}
int totemnet_iface_get (
hdb_handle_t handle,
struct totem_ip_address *addr)
{
struct totemnet_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
-
+
memcpy (addr, &instance->my_id, sizeof (struct totem_ip_address));
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
int totemnet_token_target_set (
hdb_handle_t handle,
const struct totem_ip_address *token_target)
{
struct totemnet_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemnet_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
-
+
memcpy (&instance->token_target, token_target,
sizeof (struct totem_ip_address));
hdb_handle_put (&totemnet_instance_database, handle);
error_exit:
return (res);
}
diff --git a/exec/totemnet.h b/exec/totemnet.h
index e3be2772..ea3f7760 100644
--- a/exec/totemnet.h
+++ b/exec/totemnet.h
@@ -1,108 +1,108 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2007, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TOTEMNET_H_DEFINED
#define TOTEMNET_H_DEFINED
#include <sys/types.h>
#include <sys/socket.h>
#include <corosync/totem/totem.h>
#define TOTEMNET_NOFLUSH 0
#define TOTEMNET_FLUSH 1
/*
* Totem Network interface - also does encryption/decryption
* depends on poll abstraction, POSIX, IPV4
*/
/*
* Create an instance
*/
extern int totemnet_initialize (
hdb_handle_t poll_handle,
hdb_handle_t *handle,
struct totem_config *totem_config,
int interface_no,
void *context,
void (*deliver_fn) (
void *context,
const void *msg,
size_t msg_len),
void (*iface_change_fn) (
void *context,
const struct totem_ip_address *iface_address));
extern int totemnet_processor_count_set (
hdb_handle_t handle,
int processor_count);
extern int totemnet_token_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len);
extern int totemnet_mcast_flush_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len);
extern int totemnet_mcast_noflush_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len);
extern int totemnet_recv_flush (hdb_handle_t handle);
extern int totemnet_send_flush (hdb_handle_t handle);
extern int totemnet_iface_check (hdb_handle_t handle);
extern int totemnet_finalize (hdb_handle_t handle);
extern void totemnet_net_mtu_adjust (struct totem_config *totem_config);
extern const char *totemnet_iface_print (hdb_handle_t handle);
extern int totemnet_iface_get (
hdb_handle_t handle,
struct totem_ip_address *addr);
extern int totemnet_token_target_set (
hdb_handle_t handle,
const struct totem_ip_address *token_target);
#endif /* TOTEMNET_H_DEFINED */
diff --git a/exec/totempg.c b/exec/totempg.c
index 47f84136..fdcd8e18 100644
--- a/exec/totempg.c
+++ b/exec/totempg.c
@@ -1,1338 +1,1338 @@
/*
* Copyright (c) 2003-2005 MontaVista Software, Inc.
* Copyright (c) 2005 OSDL.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
* Author: Mark Haverkamp (markh@osdl.org)
*
* 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.
*/
/*
* FRAGMENTATION AND PACKING ALGORITHM:
*
* Assemble the entire message into one buffer
* if full fragment
* store fragment into lengths list
* for each full fragment
* multicast fragment
* set length and fragment fields of pg mesage
* store remaining multicast into head of fragmentation data and set lens field
*
* If a message exceeds the maximum packet size allowed by the totem
* single ring protocol, the protocol could lose forward progress.
* Statically calculating the allowed data amount doesn't work because
* the amount of data allowed depends on the number of fragments in
* each message. In this implementation, the maximum fragment size
* is dynamically calculated for each fragment added to the message.
* It is possible for a message to be two bytes short of the maximum
* packet size. This occurs when a message or collection of
* messages + the mcast header + the lens are two bytes short of the
* end of the packet. Since another len field consumes two bytes, the
* len field would consume the rest of the packet without room for data.
*
* One optimization would be to forgo the final len field and determine
* it from the size of the udp datagram. Then this condition would no
* longer occur.
*/
/*
* ASSEMBLY AND UNPACKING ALGORITHM:
*
* copy incoming packet into assembly data buffer indexed by current
* location of end of fragment
*
* if not fragmented
* deliver all messages in assembly data buffer
* else
* if msg_count > 1 and fragmented
* deliver all messages except last message in assembly data buffer
* copy last fragmented section to start of assembly data buffer
* else
* if msg_count = 1 and fragmented
* do nothing
*
*/
#include <config.h>
#include <netinet/in.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <errno.h>
#include <corosync/swab.h>
#include <corosync/hdb.h>
#include <corosync/list.h>
#include <corosync/totem/coropoll.h>
#include <corosync/totem/totempg.h>
#include "totemmrp.h"
#include "totemsrp.h"
#define min(a,b) ((a) < (b)) ? a : b
struct totempg_mcast_header {
short version;
short type;
};
/*
* totempg_mcast structure
*
* header: Identify the mcast.
* fragmented: Set if this message continues into next message
* continuation: Set if this message is a continuation from last message
* msg_count Indicates how many packed messages are contained
* in the mcast.
* Also, the size of each packed message and the messages themselves are
* appended to the end of this structure when sent.
*/
struct totempg_mcast {
struct totempg_mcast_header header;
- unsigned char fragmented;
- unsigned char continuation;
+ unsigned char fragmented;
+ unsigned char continuation;
unsigned short msg_count;
/*
* short msg_len[msg_count];
- */
- /*
+ */
+ /*
* data for messages
*/
-};
+};
/*
* Maximum packet size for totem pg messages
*/
#define TOTEMPG_PACKET_SIZE (totempg_totem_config->net_mtu - \
sizeof (struct totempg_mcast))
/*
* Local variables used for packing small messages
*/
static unsigned short mcast_packed_msg_lens[FRAME_SIZE_MAX];
static int mcast_packed_msg_count = 0;
static int totempg_reserved = 0;
/*
* Function and data used to log messages
*/
static int totempg_log_level_security;
static int totempg_log_level_error;
static int totempg_log_level_warning;
static int totempg_log_level_notice;
static int totempg_log_level_debug;
static int totempg_subsys_id;
static void (*totempg_log_printf) (int subsys_id, const char *function,
const char *file, int line, unsigned int level,
const char *format, ...) __attribute__((format(printf, 6, 7)));
struct totem_config *totempg_totem_config;
enum throw_away_mode {
THROW_AWAY_INACTIVE,
THROW_AWAY_ACTIVE
};
struct assembly {
unsigned int nodeid;
unsigned char data[MESSAGE_SIZE_MAX];
int index;
unsigned char last_frag_num;
enum throw_away_mode throw_away_mode;
struct list_head list;
};
static void assembly_deref (struct assembly *assembly);
static int callback_token_received_fn (enum totem_callback_token_type type,
const void *data);
DECLARE_LIST_INIT(assembly_list_inuse);
DECLARE_LIST_INIT(assembly_list_free);
/*
* Staging buffer for packed messages. Messages are staged in this buffer
- * before sending. Multiple messages may fit which cuts down on the
- * number of mcasts sent. If a message doesn't completely fit, then
- * the mcast header has a fragment bit set that says that there are more
+ * before sending. Multiple messages may fit which cuts down on the
+ * number of mcasts sent. If a message doesn't completely fit, then
+ * the mcast header has a fragment bit set that says that there are more
* data to follow. fragment_size is an index into the buffer. It indicates
- * the size of message data and where to place new message data.
- * fragment_contuation indicates whether the first packed message in
+ * the size of message data and where to place new message data.
+ * fragment_contuation indicates whether the first packed message in
* the buffer is a continuation of a previously packed fragment.
*/
static unsigned char *fragmentation_data;
static int fragment_size = 0;
static int fragment_continuation = 0;
static struct iovec iov_delv;
static unsigned int totempg_max_handle = 0;
struct totempg_group_instance {
void (*deliver_fn) (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required);
void (*confchg_fn) (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id);
struct totempg_group *groups;
int groups_cnt;
};
DECLARE_HDB_DATABASE (totempg_groups_instance_database);
static unsigned char next_fragment = 1;
static pthread_mutex_t totempg_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t callback_token_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mcast_msg_mutex = PTHREAD_MUTEX_INITIALIZER;
#define log_printf(level, format, args...) \
do { \
totempg_log_printf (totempg_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, level, format, ##args); \
} while (0);
static int msg_count_send_ok (int msg_count);
static int byte_count_send_ok (int byte_count);
static struct assembly *assembly_ref (unsigned int nodeid)
{
struct assembly *assembly;
struct list_head *list;
/*
* Search inuse list for node id and return assembly buffer if found
*/
for (list = assembly_list_inuse.next;
list != &assembly_list_inuse;
- list = list->next) {
+ list = list->next) {
assembly = list_entry (list, struct assembly, list);
if (nodeid == assembly->nodeid) {
return (assembly);
}
}
/*
* Nothing found in inuse list get one from free list if available
*/
if (list_empty (&assembly_list_free) == 0) {
assembly = list_entry (assembly_list_free.next, struct assembly, list);
list_del (&assembly->list);
list_add (&assembly->list, &assembly_list_inuse);
assembly->nodeid = nodeid;
assembly->index = 0;
assembly->last_frag_num = 0;
assembly->throw_away_mode = THROW_AWAY_INACTIVE;
return (assembly);
}
/*
* Nothing available in inuse or free list, so allocate a new one
*/
assembly = malloc (sizeof (struct assembly));
/*
* TODO handle memory allocation failure here
*/
assert (assembly);
assembly->nodeid = nodeid;
assembly->data[0] = 0;
assembly->index = 0;
assembly->last_frag_num = 0;
assembly->throw_away_mode = THROW_AWAY_INACTIVE;
list_init (&assembly->list);
list_add (&assembly->list, &assembly_list_inuse);
return (assembly);
}
static void assembly_deref (struct assembly *assembly)
{
list_del (&assembly->list);
list_add (&assembly->list, &assembly_list_free);
}
static inline void app_confchg_fn (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id)
{
int i;
struct totempg_group_instance *instance;
unsigned int res;
for (i = 0; i <= totempg_max_handle; i++) {
res = hdb_handle_get (&totempg_groups_instance_database,
hdb_nocheck_convert (i), (void *)&instance);
if (res == 0) {
if (instance->confchg_fn) {
instance->confchg_fn (
configuration_type,
member_list,
member_list_entries,
left_list,
left_list_entries,
joined_list,
joined_list_entries,
ring_id);
}
hdb_handle_put (&totempg_groups_instance_database,
hdb_nocheck_convert (i));
}
}
}
static inline void group_endian_convert (
struct iovec *iovec)
{
unsigned short *group_len;
int i;
struct iovec iovec_aligned = { NULL, 0 };
struct iovec *iovec_swab;
/*
* Align data structure for sparc and ia64
*/
if ((size_t)iovec->iov_base % 4 != 0) {
iovec_aligned.iov_base = alloca(iovec->iov_len);
memcpy(iovec_aligned.iov_base, iovec->iov_base, iovec->iov_len);
iovec_aligned.iov_len = iovec->iov_len;
iovec_swab = &iovec_aligned;
} else {
iovec_swab = iovec;
}
group_len = (unsigned short *)iovec_swab->iov_base;
group_len[0] = swab16(group_len[0]);
for (i = 1; i < group_len[0] + 1; i++) {
group_len[i] = swab16(group_len[i]);
}
if (iovec_swab == &iovec_aligned) {
memcpy(iovec->iov_base, iovec_aligned.iov_base, iovec->iov_len);
}
}
static inline int group_matches (
struct iovec *iovec,
unsigned int iov_len,
struct totempg_group *groups_b,
unsigned int group_b_cnt,
unsigned int *adjust_iovec)
{
unsigned short *group_len;
char *group_name;
int i;
int j;
struct iovec iovec_aligned = { NULL, 0 };
-
+
assert (iov_len == 1);
/*
* Align data structure for sparc and ia64
*/
if ((size_t)iovec->iov_base % 4 != 0) {
iovec_aligned.iov_base = alloca(iovec->iov_len);
memcpy(iovec_aligned.iov_base, iovec->iov_base, iovec->iov_len);
iovec_aligned.iov_len = iovec->iov_len;
iovec = &iovec_aligned;
}
group_len = (unsigned short *)iovec->iov_base;
group_name = ((char *)iovec->iov_base) +
sizeof (unsigned short) * (group_len[0] + 1);
/*
* Calculate amount to adjust the iovec by before delivering to app
*/
*adjust_iovec = sizeof (unsigned short) * (group_len[0] + 1);
for (i = 1; i < group_len[0] + 1; i++) {
*adjust_iovec += group_len[i];
}
/*
* Determine if this message should be delivered to this instance
*/
for (i = 1; i < group_len[0] + 1; i++) {
for (j = 0; j < group_b_cnt; j++) {
if ((group_len[i] == groups_b[j].group_len) &&
(memcmp (groups_b[j].group, group_name, group_len[i]) == 0)) {
return (1);
}
}
group_name += group_len[i];
}
return (0);
}
-
+
static inline void app_deliver_fn (
unsigned int nodeid,
struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required)
{
int i;
struct totempg_group_instance *instance;
struct iovec stripped_iovec;
unsigned int adjust_iovec;
unsigned int res;
struct iovec aligned_iovec = { NULL, 0 };
if (endian_conversion_required) {
group_endian_convert (iovec);
}
/*
* Align data structure for sparc and ia64
*/
aligned_iovec.iov_base = alloca(iovec->iov_len);
aligned_iovec.iov_len = iovec->iov_len;
memcpy(aligned_iovec.iov_base, iovec->iov_base, iovec->iov_len);
iovec = &aligned_iovec;
for (i = 0; i <= totempg_max_handle; i++) {
res = hdb_handle_get (&totempg_groups_instance_database,
hdb_nocheck_convert (i), (void *)&instance);
if (res == 0) {
assert (iov_len == 1);
if (group_matches (iovec, iov_len, instance->groups, instance->groups_cnt, &adjust_iovec)) {
stripped_iovec.iov_len = iovec->iov_len - adjust_iovec;
// stripped_iovec.iov_base = (char *)iovec->iov_base + adjust_iovec;
/*
* Align data structure for sparc and ia64
*/
if ((char *)iovec->iov_base + adjust_iovec % 4 != 0) {
/*
* Deal with misalignment
*/
stripped_iovec.iov_base =
alloca (stripped_iovec.iov_len);
memcpy (stripped_iovec.iov_base,
(char *)iovec->iov_base + adjust_iovec,
stripped_iovec.iov_len);
}
instance->deliver_fn (
nodeid,
&stripped_iovec,
iov_len,
endian_conversion_required);
}
hdb_handle_put (&totempg_groups_instance_database, hdb_nocheck_convert(i));
}
}
}
static void totempg_confchg_fn (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id)
{
// TODO optimize this
app_confchg_fn (configuration_type,
member_list, member_list_entries,
left_list, left_list_entries,
joined_list, joined_list_entries,
ring_id);
}
static void totempg_deliver_fn (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required)
{
struct totempg_mcast *mcast;
unsigned short *msg_lens;
int i;
struct assembly *assembly;
char header[FRAME_SIZE_MAX];
int h_index;
int a_i = 0;
int msg_count;
int continuation;
int start;
assembly = assembly_ref (nodeid);
assert (assembly);
/*
* Assemble the header into one block of data and
* assemble the packet contents into one block of data to simplify delivery
*/
if (iov_len == 1) {
- /*
- * This message originated from external processor
+ /*
+ * This message originated from external processor
* because there is only one iovec for the full msg.
*/
char *data;
int datasize;
mcast = (struct totempg_mcast *)iovec[0].iov_base;
if (endian_conversion_required) {
mcast->msg_count = swab16 (mcast->msg_count);
}
msg_count = mcast->msg_count;
datasize = sizeof (struct totempg_mcast) +
msg_count * sizeof (unsigned short);
-
+
memcpy (header, iovec[0].iov_base, datasize);
assert(iovec);
data = iovec[0].iov_base;
msg_lens = (unsigned short *) (header + sizeof (struct totempg_mcast));
if (endian_conversion_required) {
for (i = 0; i < mcast->msg_count; i++) {
msg_lens[i] = swab16 (msg_lens[i]);
}
}
memcpy (&assembly->data[assembly->index], &data[datasize],
iovec[0].iov_len - datasize);
} else {
- /*
- * The message originated from local processor
+ /*
+ * The message originated from local processor
* becasue there is greater than one iovec for then full msg.
*/
h_index = 0;
for (i = 0; i < 2; i++) {
memcpy (&header[h_index], iovec[i].iov_base, iovec[i].iov_len);
h_index += iovec[i].iov_len;
}
mcast = (struct totempg_mcast *)header;
// TODO make sure we are using a copy of mcast not the actual data itself
msg_lens = (unsigned short *) (header + sizeof (struct totempg_mcast));
for (i = 2; i < iov_len; i++) {
a_i = assembly->index;
assert (iovec[i].iov_len + a_i <= MESSAGE_SIZE_MAX);
memcpy (&assembly->data[a_i], iovec[i].iov_base, iovec[i].iov_len);
a_i += msg_lens[i - 2];
}
iov_len -= 2;
}
/*
* If the last message in the buffer is a fragment, then we
* can't deliver it. We'll first deliver the full messages
- * then adjust the assembly buffer so we can add the rest of the
+ * then adjust the assembly buffer so we can add the rest of the
* fragment when it arrives.
*/
msg_count = mcast->fragmented ? mcast->msg_count - 1 : mcast->msg_count;
continuation = mcast->continuation;
iov_delv.iov_base = &assembly->data[0];
iov_delv.iov_len = assembly->index + msg_lens[0];
/*
* Make sure that if this message is a continuation, that it
* matches the sequence number of the previous fragment.
* Also, if the first packed message is a continuation
* of a previous message, but the assembly buffer
* is empty, then we need to discard it since we can't
- * assemble a complete message. Likewise, if this message isn't a
+ * assemble a complete message. Likewise, if this message isn't a
* continuation and the assembly buffer is empty, we have to discard
* the continued message.
*/
start = 0;
if (assembly->throw_away_mode == THROW_AWAY_ACTIVE) {
/* Throw away the first msg block */
if (mcast->fragmented == 0 || mcast->fragmented == 1) {
assembly->throw_away_mode = THROW_AWAY_INACTIVE;
assembly->index += msg_lens[0];
iov_delv.iov_base = &assembly->data[assembly->index];
iov_delv.iov_len = msg_lens[1];
start = 1;
}
- } else
+ } else
if (assembly->throw_away_mode == THROW_AWAY_INACTIVE) {
if (continuation == assembly->last_frag_num) {
assembly->last_frag_num = mcast->fragmented;
for (i = start; i < msg_count; i++) {
app_deliver_fn(nodeid, &iov_delv, 1,
endian_conversion_required);
assembly->index += msg_lens[i];
iov_delv.iov_base = &assembly->data[assembly->index];
if (i < (msg_count - 1)) {
iov_delv.iov_len = msg_lens[i + 1];
}
}
} else {
assembly->throw_away_mode = THROW_AWAY_ACTIVE;
}
}
if (mcast->fragmented == 0) {
/*
* End of messages, dereference assembly struct
*/
assembly->last_frag_num = 0;
assembly->index = 0;
assembly_deref (assembly);
} else {
/*
* Message is fragmented, keep around assembly list
*/
if (mcast->msg_count > 1) {
memmove (&assembly->data[0],
&assembly->data[assembly->index],
msg_lens[msg_count]);
assembly->index = 0;
}
assembly->index += msg_lens[msg_count];
}
}
/*
* Totem Process Group Abstraction
* depends on poll abstraction, POSIX, IPV4
*/
void *callback_token_received_handle;
int callback_token_received_fn (enum totem_callback_token_type type,
const void *data)
{
struct totempg_mcast mcast;
struct iovec iovecs[3];
int res;
pthread_mutex_lock (&mcast_msg_mutex);
if (mcast_packed_msg_count == 0) {
pthread_mutex_unlock (&mcast_msg_mutex);
return (0);
}
if (totemmrp_avail() == 0) {
pthread_mutex_unlock (&mcast_msg_mutex);
return (0);
}
mcast.fragmented = 0;
/*
* Was the first message in this buffer a continuation of a
* fragmented message?
*/
mcast.continuation = fragment_continuation;
fragment_continuation = 0;
mcast.msg_count = mcast_packed_msg_count;
iovecs[0].iov_base = &mcast;
iovecs[0].iov_len = sizeof (struct totempg_mcast);
iovecs[1].iov_base = mcast_packed_msg_lens;
iovecs[1].iov_len = mcast_packed_msg_count * sizeof (unsigned short);
iovecs[2].iov_base = &fragmentation_data[0];
iovecs[2].iov_len = fragment_size;
res = totemmrp_mcast (iovecs, 3, 0);
mcast_packed_msg_count = 0;
fragment_size = 0;
pthread_mutex_unlock (&mcast_msg_mutex);
return (0);
}
/*
* Initialize the totem process group abstraction
*/
int totempg_initialize (
hdb_handle_t poll_handle,
struct totem_config *totem_config)
{
int res;
totempg_totem_config = totem_config;
totempg_log_level_security = totem_config->totem_logging_configuration.log_level_security;
totempg_log_level_error = totem_config->totem_logging_configuration.log_level_error;
totempg_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
totempg_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
totempg_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
totempg_log_printf = totem_config->totem_logging_configuration.log_printf;
totempg_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
fragmentation_data = malloc (TOTEMPG_PACKET_SIZE);
if (fragmentation_data == 0) {
return (-1);
}
res = totemmrp_initialize (
poll_handle,
totem_config,
totempg_deliver_fn,
totempg_confchg_fn);
totemmrp_callback_token_create (
- &callback_token_received_handle,
+ &callback_token_received_handle,
TOTEM_CALLBACK_TOKEN_RECEIVED,
0,
callback_token_received_fn,
0);
totemsrp_net_mtu_adjust (totem_config);
return (res);
}
void totempg_finalize (void)
{
pthread_mutex_lock (&totempg_mutex);
totemmrp_finalize ();
pthread_mutex_unlock (&totempg_mutex);
}
/*
* Multicast a message
*/
static int mcast_msg (
struct iovec *iovec_in,
unsigned 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_len = 0;
int copy_base = 0;
int total_size = 0;
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));
mcast_packed_msg_lens[mcast_packed_msg_count] = 0;
/*
* Check if we would overwrite new message queue
*/
for (i = 0; i < iov_len; i++) {
total_size += iovec[i].iov_len;
}
if (byte_count_send_ok (total_size + sizeof(unsigned short) *
(mcast_packed_msg_count+1)) == 0) {
pthread_mutex_unlock (&mcast_msg_mutex);
return(-1);
}
for (i = 0; i < iov_len; ) {
mcast.fragmented = 0;
mcast.continuation = fragment_continuation;
copy_len = iovec[i].iov_len - copy_base;
/*
* If it all fits with room left over, copy it in.
* We need to leave at least sizeof(short) + 1 bytes in the
* fragment_buffer on exit so that max_packet_size + fragment_size
* doesn't exceed the size of the fragment_buffer on the next call.
*/
- if ((copy_len + fragment_size) <
+ if ((copy_len + fragment_size) <
(max_packet_size - sizeof (unsigned short))) {
memcpy (&fragmentation_data[fragment_size],
(char *)iovec[i].iov_base + copy_base, copy_len);
fragment_size += copy_len;
mcast_packed_msg_lens[mcast_packed_msg_count] += copy_len;
next_fragment = 1;
copy_len = 0;
copy_base = 0;
i++;
continue;
/*
* If it just fits or is too big, then send out what fits.
*/
} else {
unsigned char *data_ptr;
copy_len = min(copy_len, max_packet_size - fragment_size);
if( copy_len == max_packet_size )
data_ptr = (unsigned char *)iovec[i].iov_base + copy_base;
else {
data_ptr = fragmentation_data;
memcpy (&fragmentation_data[fragment_size],
(unsigned char *)iovec[i].iov_base + copy_base, copy_len);
}
memcpy (&fragmentation_data[fragment_size],
(unsigned char *)iovec[i].iov_base + copy_base, copy_len);
mcast_packed_msg_lens[mcast_packed_msg_count] += copy_len;
/*
* if we're not on the last iovec or the iovec is too large to
* fit, then indicate a fragment. This also means that the next
* message will have the continuation of this one.
*/
- if ((i < (iov_len - 1)) ||
+ if ((i < (iov_len - 1)) ||
((copy_base + copy_len) < iovec[i].iov_len)) {
if (!next_fragment) {
next_fragment++;
}
fragment_continuation = next_fragment;
mcast.fragmented = next_fragment++;
assert(fragment_continuation != 0);
assert(mcast.fragmented != 0);
} else {
fragment_continuation = 0;
}
/*
* assemble the message and send it
*/
mcast.msg_count = ++mcast_packed_msg_count;
iovecs[0].iov_base = &mcast;
iovecs[0].iov_len = sizeof(struct totempg_mcast);
iovecs[1].iov_base = mcast_packed_msg_lens;
- iovecs[1].iov_len = mcast_packed_msg_count *
+ iovecs[1].iov_len = mcast_packed_msg_count *
sizeof(unsigned short);
iovecs[2].iov_base = data_ptr;
iovecs[2].iov_len = max_packet_size;
assert (totemmrp_avail() > 0);
res = totemmrp_mcast (iovecs, 3, guarantee);
/*
* Recalculate counts and indexes for the next.
*/
mcast_packed_msg_lens[0] = 0;
mcast_packed_msg_count = 0;
fragment_size = 0;
max_packet_size = TOTEMPG_PACKET_SIZE - (sizeof(unsigned short));
/*
* If the iovec all fit, go to the next iovec
*/
if ((copy_base + copy_len) == iovec[i].iov_len) {
copy_len = 0;
copy_base = 0;
i++;
-
+
/*
* Continue with the rest of the current iovec.
*/
} else {
copy_base += copy_len;
}
}
}
/*
* Bump only if we added message data. This may be zero if
* the last buffer just fit into the fragmentation_data buffer
* and we were at the last iovec.
*/
if (mcast_packed_msg_lens[mcast_packed_msg_count]) {
mcast_packed_msg_count++;
}
pthread_mutex_unlock (&mcast_msg_mutex);
return (res);
}
/*
* Determine if a message of msg_size could be queued
*/
static int msg_count_send_ok (
int msg_count)
{
int avail = 0;
avail = totemmrp_avail () - totempg_reserved - 1;
-
+
return (avail > msg_count);
}
static int byte_count_send_ok (
int byte_count)
{
unsigned int msg_count = 0;
int avail = 0;
avail = totemmrp_avail () - 1;
- msg_count = (byte_count / (totempg_totem_config->net_mtu - 25)) + 1;
+ msg_count = (byte_count / (totempg_totem_config->net_mtu - 25)) + 1;
return (avail > msg_count);
}
static int send_reserve (
int msg_size)
{
unsigned int msg_count = 0;
- msg_count = (msg_size / (totempg_totem_config->net_mtu - 25)) + 1;
+ msg_count = (msg_size / (totempg_totem_config->net_mtu - 25)) + 1;
totempg_reserved += msg_count;
return (msg_count);
}
static void send_release (
int msg_count)
{
totempg_reserved -= msg_count;
}
int totempg_callback_token_create (
void **handle_out,
enum totem_callback_token_type type,
int delete,
int (*callback_fn) (enum totem_callback_token_type type, const void *),
const void *data)
{
unsigned int res;
pthread_mutex_lock (&callback_token_mutex);
res = totemmrp_callback_token_create (handle_out, type, delete,
callback_fn, data);
pthread_mutex_unlock (&callback_token_mutex);
return (res);
}
void totempg_callback_token_destroy (
void *handle_out)
{
pthread_mutex_lock (&callback_token_mutex);
totemmrp_callback_token_destroy (handle_out);
pthread_mutex_unlock (&callback_token_mutex);
}
/*
* vi: set autoindent tabstop=4 shiftwidth=4 :
*/
int totempg_groups_initialize (
hdb_handle_t *handle,
void (*deliver_fn) (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required),
void (*confchg_fn) (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id))
{
struct totempg_group_instance *instance;
unsigned int res;
pthread_mutex_lock (&totempg_mutex);
res = hdb_handle_create (&totempg_groups_instance_database,
sizeof (struct totempg_group_instance), handle);
if (res != 0) {
goto error_exit;
}
if (*handle > totempg_max_handle) {
totempg_max_handle = *handle;
}
res = hdb_handle_get (&totempg_groups_instance_database, *handle,
(void *)&instance);
if (res != 0) {
goto error_destroy;
}
instance->deliver_fn = deliver_fn;
instance->confchg_fn = confchg_fn;
instance->groups = 0;
instance->groups_cnt = 0;
hdb_handle_put (&totempg_groups_instance_database, *handle);
pthread_mutex_unlock (&totempg_mutex);
return (0);
error_destroy:
hdb_handle_destroy (&totempg_groups_instance_database, *handle);
error_exit:
pthread_mutex_unlock (&totempg_mutex);
return (-1);
}
int totempg_groups_join (
hdb_handle_t handle,
const struct totempg_group *groups,
size_t group_cnt)
{
struct totempg_group_instance *instance;
struct totempg_group *new_groups;
unsigned int res;
pthread_mutex_lock (&totempg_mutex);
res = hdb_handle_get (&totempg_groups_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
new_groups = realloc (instance->groups,
sizeof (struct totempg_group) *
(instance->groups_cnt + group_cnt));
if (new_groups == 0) {
res = ENOMEM;
goto error_exit;
}
- memcpy (&new_groups[instance->groups_cnt],
+ memcpy (&new_groups[instance->groups_cnt],
groups, group_cnt * sizeof (struct totempg_group));
instance->groups = new_groups;
instance->groups_cnt = instance->groups_cnt = group_cnt;
hdb_handle_put (&totempg_groups_instance_database, handle);
error_exit:
pthread_mutex_unlock (&totempg_mutex);
return (res);
}
int totempg_groups_leave (
hdb_handle_t handle,
const struct totempg_group *groups,
size_t group_cnt)
{
struct totempg_group_instance *instance;
unsigned int res;
pthread_mutex_lock (&totempg_mutex);
res = hdb_handle_get (&totempg_groups_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
hdb_handle_put (&totempg_groups_instance_database, handle);
error_exit:
pthread_mutex_unlock (&totempg_mutex);
return (res);
}
#define MAX_IOVECS_FROM_APP 32
#define MAX_GROUPS_PER_MSG 32
int totempg_groups_mcast_joined (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len,
int guarantee)
{
struct totempg_group_instance *instance;
unsigned short group_len[MAX_GROUPS_PER_MSG + 1];
struct iovec iovec_mcast[MAX_GROUPS_PER_MSG + 1 + MAX_IOVECS_FROM_APP];
int i;
unsigned int res;
pthread_mutex_lock (&totempg_mutex);
res = hdb_handle_get (&totempg_groups_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
/*
* Build group_len structure and the iovec_mcast structure
*/
group_len[0] = instance->groups_cnt;
for (i = 0; i < instance->groups_cnt; i++) {
group_len[i + 1] = instance->groups[i].group_len;
iovec_mcast[i + 1].iov_len = instance->groups[i].group_len;
iovec_mcast[i + 1].iov_base = (void *) instance->groups[i].group;
}
iovec_mcast[0].iov_len = (instance->groups_cnt + 1) * sizeof (unsigned short);
iovec_mcast[0].iov_base = group_len;
for (i = 0; i < iov_len; i++) {
iovec_mcast[i + instance->groups_cnt + 1].iov_len = iovec[i].iov_len;
iovec_mcast[i + instance->groups_cnt + 1].iov_base = iovec[i].iov_base;
}
res = mcast_msg (iovec_mcast, iov_len + instance->groups_cnt + 1, guarantee);
hdb_handle_put (&totempg_groups_instance_database, handle);
error_exit:
pthread_mutex_unlock (&totempg_mutex);
return (res);
}
int totempg_groups_joined_reserve (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totempg_group_instance *instance;
unsigned int size = 0;
unsigned int i;
unsigned int res;
unsigned int reserved = 0;
pthread_mutex_lock (&totempg_mutex);
pthread_mutex_lock (&mcast_msg_mutex);
res = hdb_handle_get (&totempg_groups_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
for (i = 0; i < instance->groups_cnt; i++) {
size += instance->groups[i].group_len;
}
for (i = 0; i < iov_len; i++) {
size += iovec[i].iov_len;
}
reserved = send_reserve (size);
if (msg_count_send_ok (reserved) == 0) {
send_release (reserved);
reserved = 0;
}
hdb_handle_put (&totempg_groups_instance_database, handle);
error_exit:
pthread_mutex_unlock (&mcast_msg_mutex);
pthread_mutex_unlock (&totempg_mutex);
return (reserved);
}
int totempg_groups_joined_release (int msg_count)
{
pthread_mutex_lock (&totempg_mutex);
pthread_mutex_lock (&mcast_msg_mutex);
send_release (msg_count);
pthread_mutex_unlock (&mcast_msg_mutex);
pthread_mutex_unlock (&totempg_mutex);
return 0;
}
int totempg_groups_mcast_groups (
hdb_handle_t handle,
int guarantee,
const struct totempg_group *groups,
size_t groups_cnt,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totempg_group_instance *instance;
unsigned short group_len[MAX_GROUPS_PER_MSG + 1];
struct iovec iovec_mcast[MAX_GROUPS_PER_MSG + 1 + MAX_IOVECS_FROM_APP];
int i;
unsigned int res;
pthread_mutex_lock (&totempg_mutex);
res = hdb_handle_get (&totempg_groups_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
/*
* Build group_len structure and the iovec_mcast structure
*/
group_len[0] = groups_cnt;
for (i = 0; i < groups_cnt; i++) {
group_len[i + 1] = groups[i].group_len;
iovec_mcast[i + 1].iov_len = groups[i].group_len;
iovec_mcast[i + 1].iov_base = (void *) groups[i].group;
}
iovec_mcast[0].iov_len = (groups_cnt + 1) * sizeof (unsigned short);
iovec_mcast[0].iov_base = group_len;
for (i = 0; i < iov_len; i++) {
iovec_mcast[i + groups_cnt + 1].iov_len = iovec[i].iov_len;
iovec_mcast[i + groups_cnt + 1].iov_base = iovec[i].iov_base;
}
res = mcast_msg (iovec_mcast, iov_len + groups_cnt + 1, guarantee);
hdb_handle_put (&totempg_groups_instance_database, handle);
error_exit:
pthread_mutex_unlock (&totempg_mutex);
return (res);
}
/*
* Returns -1 if error, 0 if can't send, 1 if can send the message
*/
int totempg_groups_send_ok_groups (
hdb_handle_t handle,
const struct totempg_group *groups,
size_t groups_cnt,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totempg_group_instance *instance;
unsigned int size = 0;
unsigned int i;
unsigned int res;
pthread_mutex_lock (&totempg_mutex);
res = hdb_handle_get (&totempg_groups_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
for (i = 0; i < groups_cnt; i++) {
size += groups[i].group_len;
}
for (i = 0; i < iov_len; i++) {
size += iovec[i].iov_len;
}
res = msg_count_send_ok (size);
-
+
hdb_handle_put (&totempg_groups_instance_database, handle);
error_exit:
pthread_mutex_unlock (&totempg_mutex);
return (res);
}
int totempg_ifaces_get (
unsigned int nodeid,
struct totem_ip_address *interfaces,
char ***status,
unsigned int *iface_count)
{
int res;
res = totemmrp_ifaces_get (
nodeid,
interfaces,
status,
iface_count);
return (res);
}
int totempg_ring_reenable (void)
{
int res;
res = totemmrp_ring_reenable ();
return (res);
}
const char *totempg_ifaces_print (unsigned int nodeid)
{
static char iface_string[256 * INTERFACE_MAX];
char one_iface[64];
struct totem_ip_address interfaces[INTERFACE_MAX];
char **status;
unsigned int iface_count;
unsigned int i;
int res;
iface_string[0] = '\0';
res = totempg_ifaces_get (nodeid, interfaces, &status, &iface_count);
if (res == -1) {
return ("no interface found for nodeid");
}
for (i = 0; i < iface_count; i++) {
sprintf (one_iface, "r(%d) ip(%s) ",
i, totemip_print (&interfaces[i]));
strcat (iface_string, one_iface);
}
return (iface_string);
}
unsigned int totempg_my_nodeid_get (void)
{
return (totemmrp_my_nodeid_get());
}
int totempg_my_family_get (void)
{
return (totemmrp_my_family_get());
}
diff --git a/exec/totemrrp.c b/exec/totemrrp.c
index d28dc5be..32720478 100644
--- a/exec/totemrrp.c
+++ b/exec/totemrrp.c
@@ -1,1738 +1,1738 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <corosync/queue.h>
#include <corosync/sq.h>
#include <corosync/list.h>
#include <corosync/hdb.h>
#include <corosync/swab.h>
#include <corosync/totem/coropoll.h>
#include "totemnet.h"
#include "totemrrp.h"
void rrp_deliver_fn (
void *context,
const void *msg,
size_t msg_len);
void rrp_iface_change_fn (
void *context,
const struct totem_ip_address *iface_addr);
struct totemrrp_instance;
struct passive_instance {
struct totemrrp_instance *rrp_instance;
unsigned int *faulty;
unsigned int *token_recv_count;
unsigned int *mcast_recv_count;
unsigned char token[15000];
unsigned int token_len;
poll_timer_handle timer_expired_token;
poll_timer_handle timer_problem_decrementer;
void *totemrrp_context;
unsigned int token_xmit_iface;
unsigned int msg_xmit_iface;
};
struct active_instance {
struct totemrrp_instance *rrp_instance;
unsigned int *faulty;
unsigned int *last_token_recv;
unsigned int *counter_problems;
unsigned char token[15000];
unsigned int token_len;
unsigned int last_token_seq;
poll_timer_handle timer_expired_token;
poll_timer_handle timer_problem_decrementer;
void *totemrrp_context;
};
struct rrp_algo {
const char *name;
void * (*initialize) (
struct totemrrp_instance *rrp_instance,
int interface_count);
void (*mcast_recv) (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len);
void (*mcast_noflush_send) (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
void (*mcast_flush_send) (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
void (*token_recv) (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seqid);
void (*token_send) (
struct totemrrp_instance *instance,
const struct iovec *iovec,
- unsigned int iov_len);
+ unsigned int iov_len);
void (*recv_flush) (
struct totemrrp_instance *instance);
void (*send_flush) (
struct totemrrp_instance *instance);
void (*iface_check) (
struct totemrrp_instance *instance);
void (*processor_count_set) (
struct totemrrp_instance *instance,
unsigned int processor_count);
void (*token_target_set) (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no);
void (*ring_reenable) (
struct totemrrp_instance *instance);
};
struct totemrrp_instance {
hdb_handle_t totemrrp_poll_handle;
struct totem_interface *interfaces;
struct rrp_algo *rrp_algo;
void *context;
-
+
char *status[INTERFACE_MAX];
void (*totemrrp_deliver_fn) (
void *context,
const void *msg,
size_t msg_len);
void (*totemrrp_iface_change_fn) (
void *context,
const struct totem_ip_address *iface_addr,
unsigned int iface_no);
void (*totemrrp_token_seqid_get) (
const void *msg,
unsigned int *seqid,
unsigned int *token_is);
unsigned int (*totemrrp_msgs_missing) (void);
/*
* Function and data used to log messages
*/
int totemrrp_log_level_security;
int totemrrp_log_level_error;
int totemrrp_log_level_warning;
int totemrrp_log_level_notice;
int totemrrp_log_level_debug;
int totemrrp_subsys_id;
void (*totemrrp_log_printf) (int subsys, const char *function,
const char *file, int line, unsigned int level,
const char *format, ...)__attribute__((format(printf, 6, 7)));
hdb_handle_t handle;
hdb_handle_t *net_handles;
void *rrp_algo_instance;
int interface_count;
hdb_handle_t poll_handle;
int processor_count;
struct totem_config *totem_config;
};
/*
* None Replication Forward Declerations
*/
static void none_mcast_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len);
static void none_mcast_noflush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
static void none_mcast_flush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
static void none_token_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seqid);
static void none_token_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
- unsigned int iov_len);
+ unsigned int iov_len);
static void none_recv_flush (
struct totemrrp_instance *instance);
static void none_send_flush (
struct totemrrp_instance *instance);
static void none_iface_check (
struct totemrrp_instance *instance);
static void none_processor_count_set (
struct totemrrp_instance *instance,
unsigned int processor_count_set);
static void none_token_target_set (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no);
static void none_ring_reenable (
struct totemrrp_instance *instance);
/*
* Passive Replication Forward Declerations
*/
static void *passive_instance_initialize (
struct totemrrp_instance *rrp_instance,
int interface_count);
static void passive_mcast_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len);
static void passive_mcast_noflush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
static void passive_mcast_flush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
static void passive_token_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seqid);
static void passive_token_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
- unsigned int iov_len);
+ unsigned int iov_len);
static void passive_recv_flush (
struct totemrrp_instance *instance);
static void passive_send_flush (
struct totemrrp_instance *instance);
static void passive_iface_check (
struct totemrrp_instance *instance);
static void passive_processor_count_set (
struct totemrrp_instance *instance,
unsigned int processor_count_set);
static void passive_token_target_set (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no);
static void passive_ring_reenable (
struct totemrrp_instance *instance);
/*
* Active Replication Forward Definitions
*/
static void *active_instance_initialize (
struct totemrrp_instance *rrp_instance,
int interface_count);
static void active_mcast_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len);
static void active_mcast_noflush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
static void active_mcast_flush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len);
static void active_token_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seqid);
static void active_token_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
- unsigned int iov_len);
+ unsigned int iov_len);
static void active_recv_flush (
struct totemrrp_instance *instance);
static void active_send_flush (
struct totemrrp_instance *instance);
static void active_iface_check (
struct totemrrp_instance *instance);
static void active_processor_count_set (
struct totemrrp_instance *instance,
unsigned int processor_count_set);
static void active_token_target_set (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no);
static void active_ring_reenable (
struct totemrrp_instance *instance);
static void active_timer_expired_token_start (
struct active_instance *active_instance);
static void active_timer_expired_token_cancel (
struct active_instance *active_instance);
static void active_timer_problem_decrementer_start (
struct active_instance *active_instance);
static void active_timer_problem_decrementer_cancel (
struct active_instance *active_instance);
struct rrp_algo none_algo = {
.name = "none",
.initialize = NULL,
.mcast_recv = none_mcast_recv,
.mcast_noflush_send = none_mcast_noflush_send,
.mcast_flush_send = none_mcast_flush_send,
.token_recv = none_token_recv,
.token_send = none_token_send,
.recv_flush = none_recv_flush,
.send_flush = none_send_flush,
.iface_check = none_iface_check,
.processor_count_set = none_processor_count_set,
.token_target_set = none_token_target_set,
.ring_reenable = none_ring_reenable
};
struct rrp_algo passive_algo = {
.name = "passive",
.initialize = passive_instance_initialize,
.mcast_recv = passive_mcast_recv,
.mcast_noflush_send = passive_mcast_noflush_send,
.mcast_flush_send = passive_mcast_flush_send,
.token_recv = passive_token_recv,
.token_send = passive_token_send,
.recv_flush = passive_recv_flush,
.send_flush = passive_send_flush,
.iface_check = passive_iface_check,
.processor_count_set = passive_processor_count_set,
.token_target_set = passive_token_target_set,
.ring_reenable = passive_ring_reenable
};
struct rrp_algo active_algo = {
.name = "active",
.initialize = active_instance_initialize,
.mcast_recv = active_mcast_recv,
.mcast_noflush_send = active_mcast_noflush_send,
.mcast_flush_send = active_mcast_flush_send,
.token_recv = active_token_recv,
.token_send = active_token_send,
.recv_flush = active_recv_flush,
.send_flush = active_send_flush,
.iface_check = active_iface_check,
.processor_count_set = active_processor_count_set,
.token_target_set = active_token_target_set,
.ring_reenable = active_ring_reenable
};
struct rrp_algo *rrp_algos[] = {
&none_algo,
&passive_algo,
&active_algo
};
#define RRP_ALGOS_COUNT 3
/*
* All instances in one database
*/
DECLARE_HDB_DATABASE (totemrrp_instance_database);
#define log_printf(level, format, args...) \
do { \
rrp_instance->totemrrp_log_printf ( \
rrp_instance->totemrrp_subsys_id, \
__FUNCTION__, __FILE__, __LINE__, level, \
format, ##args); \
} while (0);
/*
* None Replication Implementation
*/
static void none_mcast_recv (
struct totemrrp_instance *rrp_instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len)
{
rrp_instance->totemrrp_deliver_fn (
context,
msg,
msg_len);
}
static void none_mcast_flush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
totemnet_mcast_flush_send (instance->net_handles[0], iovec, iov_len);
}
static void none_mcast_noflush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
totemnet_mcast_noflush_send (instance->net_handles[0], iovec, iov_len);
}
static void none_token_recv (
struct totemrrp_instance *rrp_instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seq)
{
rrp_instance->totemrrp_deliver_fn (
context,
msg,
msg_len);
}
static void none_token_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
totemnet_token_send (
instance->net_handles[0],
iovec, iov_len);
}
static void none_recv_flush (struct totemrrp_instance *instance)
{
totemnet_recv_flush (instance->net_handles[0]);
}
static void none_send_flush (struct totemrrp_instance *instance)
{
totemnet_send_flush (instance->net_handles[0]);
}
static void none_iface_check (struct totemrrp_instance *instance)
{
totemnet_iface_check (instance->net_handles[0]);
}
static void none_processor_count_set (
struct totemrrp_instance *instance,
unsigned int processor_count)
{
totemnet_processor_count_set (instance->net_handles[0],
processor_count);
}
static void none_token_target_set (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no)
{
totemnet_token_target_set (instance->net_handles[0], token_target);
}
static void none_ring_reenable (
struct totemrrp_instance *instance)
{
/*
* No operation
*/
}
/*
* Passive Replication Implementation
*/
void *passive_instance_initialize (
struct totemrrp_instance *rrp_instance,
int interface_count)
{
struct passive_instance *instance;
instance = malloc (sizeof (struct passive_instance));
if (instance == 0) {
goto error_exit;
}
memset (instance, 0, sizeof (struct passive_instance));
instance->faulty = malloc (sizeof (int) * interface_count);
if (instance->faulty == 0) {
free (instance);
instance = 0;
goto error_exit;
}
memset (instance->faulty, 0, sizeof (int) * interface_count);
instance->token_recv_count = malloc (sizeof (int) * interface_count);
if (instance->token_recv_count == 0) {
free (instance->faulty);
free (instance);
instance = 0;
goto error_exit;
}
memset (instance->token_recv_count, 0, sizeof (int) * interface_count);
instance->mcast_recv_count = malloc (sizeof (int) * interface_count);
if (instance->mcast_recv_count == 0) {
free (instance->token_recv_count);
free (instance->faulty);
free (instance);
instance = 0;
goto error_exit;
}
memset (instance->mcast_recv_count, 0, sizeof (int) * interface_count);
error_exit:
return ((void *)instance);
}
static void timer_function_passive_token_expired (void *context)
{
struct passive_instance *passive_instance = (struct passive_instance *)context;
struct totemrrp_instance *rrp_instance = passive_instance->rrp_instance;
rrp_instance->totemrrp_deliver_fn (
passive_instance->totemrrp_context,
passive_instance->token,
passive_instance->token_len);
}
/* TODO
static void timer_function_passive_problem_decrementer (void *context)
{
// struct passive_instance *passive_instance = (struct passive_instance *)context;
// struct totemrrp_instance *rrp_instance = passive_instance->rrp_instance;
}
*/
static void passive_timer_expired_token_start (
struct passive_instance *passive_instance)
{
poll_timer_add (
passive_instance->rrp_instance->poll_handle,
passive_instance->rrp_instance->totem_config->rrp_token_expired_timeout,
(void *)passive_instance,
timer_function_passive_token_expired,
&passive_instance->timer_expired_token);
}
static void passive_timer_expired_token_cancel (
struct passive_instance *passive_instance)
{
poll_timer_delete (
passive_instance->rrp_instance->poll_handle,
passive_instance->timer_expired_token);
}
/*
static void passive_timer_problem_decrementer_start (
struct passive_instance *passive_instance)
{
poll_timer_add (
passive_instance->rrp_instance->poll_handle,
passive_instance->rrp_instance->totem_config->rrp_problem_count_timeout,
(void *)passive_instance,
timer_function_passive_problem_decrementer,
&passive_instance->timer_problem_decrementer);
}
static void passive_timer_problem_decrementer_cancel (
struct passive_instance *passive_instance)
{
poll_timer_delete (
passive_instance->rrp_instance->poll_handle,
passive_instance->timer_problem_decrementer);
}
*/
static void passive_mcast_recv (
struct totemrrp_instance *rrp_instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len)
{
struct passive_instance *passive_instance = (struct passive_instance *)rrp_instance->rrp_algo_instance;
unsigned int max;
unsigned int i;
rrp_instance->totemrrp_deliver_fn (
context,
msg,
msg_len);
if (rrp_instance->totemrrp_msgs_missing() == 0 &&
passive_instance->timer_expired_token) {
/*
* Delivers the last token
*/
rrp_instance->totemrrp_deliver_fn (
passive_instance->totemrrp_context,
passive_instance->token,
passive_instance->token_len);
passive_timer_expired_token_cancel (passive_instance);
}
/*
* Monitor for failures
* TODO doesn't handle wrap-around of the mcast recv count
*/
passive_instance->mcast_recv_count[iface_no] += 1;
max = 0;
for (i = 0; i < rrp_instance->interface_count; i++) {
if (max < passive_instance->mcast_recv_count[i]) {
max = passive_instance->mcast_recv_count[i];
}
}
for (i = 0; i < rrp_instance->interface_count; i++) {
if ((passive_instance->faulty[i] == 0) &&
- (max - passive_instance->mcast_recv_count[i] >
+ (max - passive_instance->mcast_recv_count[i] >
rrp_instance->totem_config->rrp_problem_count_threshold)) {
passive_instance->faulty[i] = 1;
- sprintf (rrp_instance->status[i],
+ sprintf (rrp_instance->status[i],
"Marking ringid %u interface %s FAULTY - adminisrtative intervention required.",
i,
totemnet_iface_print (rrp_instance->net_handles[i]));
log_printf (
rrp_instance->totemrrp_log_level_error,
"%s",
rrp_instance->status[i]);
}
}
}
static void passive_mcast_flush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
struct passive_instance *passive_instance = (struct passive_instance *)instance->rrp_algo_instance;
do {
passive_instance->msg_xmit_iface = (passive_instance->msg_xmit_iface + 1) % instance->interface_count;
} while (passive_instance->faulty[passive_instance->msg_xmit_iface] == 1);
-
+
totemnet_mcast_flush_send (instance->net_handles[passive_instance->msg_xmit_iface], iovec, iov_len);
}
static void passive_mcast_noflush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
struct passive_instance *passive_instance = (struct passive_instance *)instance->rrp_algo_instance;
do {
passive_instance->msg_xmit_iface = (passive_instance->msg_xmit_iface + 1) % instance->interface_count;
} while (passive_instance->faulty[passive_instance->msg_xmit_iface] == 1);
-
-
+
+
totemnet_mcast_noflush_send (instance->net_handles[passive_instance->msg_xmit_iface], iovec, iov_len);
}
static void passive_token_recv (
struct totemrrp_instance *rrp_instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seq)
{
struct passive_instance *passive_instance = (struct passive_instance *)rrp_instance->rrp_algo_instance;
unsigned int max;
unsigned int i;
passive_instance->totemrrp_context = context; // this should be in totemrrp_instance ? TODO
if (rrp_instance->totemrrp_msgs_missing() == 0) {
rrp_instance->totemrrp_deliver_fn (
context,
msg,
msg_len);
} else {
memcpy (passive_instance->token, msg, msg_len);
passive_timer_expired_token_start (passive_instance);
}
/*
* Monitor for failures
* TODO doesn't handle wrap-around of the token
*/
passive_instance->token_recv_count[iface_no] += 1;
max = 0;
for (i = 0; i < rrp_instance->interface_count; i++) {
if (max < passive_instance->token_recv_count[i]) {
max = passive_instance->token_recv_count[i];
}
}
for (i = 0; i < rrp_instance->interface_count; i++) {
if ((passive_instance->faulty[i] == 0) &&
- (max - passive_instance->token_recv_count[i] >
+ (max - passive_instance->token_recv_count[i] >
rrp_instance->totem_config->rrp_problem_count_threshold)) {
passive_instance->faulty[i] = 1;
- sprintf (rrp_instance->status[i],
+ sprintf (rrp_instance->status[i],
"Marking seqid %d ringid %u interface %s FAULTY - adminisrtative intervention required.",
token_seq,
i,
totemnet_iface_print (rrp_instance->net_handles[i]));
log_printf (
rrp_instance->totemrrp_log_level_error,
"%s",
rrp_instance->status[i]);
}
}
}
static void passive_token_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
struct passive_instance *passive_instance = (struct passive_instance *)instance->rrp_algo_instance;
do {
passive_instance->token_xmit_iface = (passive_instance->token_xmit_iface + 1) % instance->interface_count;
} while (passive_instance->faulty[passive_instance->token_xmit_iface] == 1);
-
+
totemnet_token_send (
instance->net_handles[passive_instance->token_xmit_iface],
iovec, iov_len);
}
static void passive_recv_flush (struct totemrrp_instance *instance)
{
struct passive_instance *rrp_algo_instance = (struct passive_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_recv_flush (instance->net_handles[i]);
}
}
}
static void passive_send_flush (struct totemrrp_instance *instance)
{
struct passive_instance *rrp_algo_instance = (struct passive_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_send_flush (instance->net_handles[i]);
}
}
}
static void passive_iface_check (struct totemrrp_instance *instance)
{
struct passive_instance *rrp_algo_instance = (struct passive_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_iface_check (instance->net_handles[i]);
}
}
}
static void passive_processor_count_set (
struct totemrrp_instance *instance,
unsigned int processor_count)
{
struct passive_instance *rrp_algo_instance = (struct passive_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_processor_count_set (instance->net_handles[i],
processor_count);
}
}
}
static void passive_token_target_set (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no)
{
totemnet_token_target_set (instance->net_handles[iface_no], token_target);
}
static void passive_ring_reenable (
struct totemrrp_instance *instance)
{
struct passive_instance *rrp_algo_instance = (struct passive_instance *)instance->rrp_algo_instance;
memset (rrp_algo_instance->mcast_recv_count, 0, sizeof (unsigned int) *
instance->interface_count);
memset (rrp_algo_instance->token_recv_count, 0, sizeof (unsigned int) *
instance->interface_count);
memset (rrp_algo_instance->faulty, 0, sizeof (unsigned int) *
instance->interface_count);
}
/*
* Active Replication Implementation
*/
void *active_instance_initialize (
struct totemrrp_instance *rrp_instance,
int interface_count)
{
struct active_instance *instance;
instance = malloc (sizeof (struct active_instance));
if (instance == 0) {
goto error_exit;
}
memset (instance, 0, sizeof (struct active_instance));
instance->faulty = malloc (sizeof (int) * interface_count);
if (instance->faulty == 0) {
free (instance);
instance = 0;
goto error_exit;
}
memset (instance->faulty, 0, sizeof (unsigned int) * interface_count);
instance->last_token_recv = malloc (sizeof (int) * interface_count);
if (instance->last_token_recv == 0) {
free (instance->faulty);
free (instance);
instance = 0;
goto error_exit;
}
memset (instance->last_token_recv, 0, sizeof (unsigned int) * interface_count);
instance->counter_problems = malloc (sizeof (int) * interface_count);
if (instance->counter_problems == 0) {
free (instance->last_token_recv);
free (instance->faulty);
free (instance);
instance = 0;
goto error_exit;
}
memset (instance->counter_problems, 0, sizeof (unsigned int) * interface_count);
instance->timer_expired_token = 0;
instance->timer_problem_decrementer = 0;
instance->rrp_instance = rrp_instance;
error_exit:
return ((void *)instance);
}
static void timer_function_active_problem_decrementer (void *context)
{
struct active_instance *active_instance = (struct active_instance *)context;
struct totemrrp_instance *rrp_instance = active_instance->rrp_instance;
unsigned int problem_found = 0;
unsigned int i;
-
+
for (i = 0; i < rrp_instance->interface_count; i++) {
if (active_instance->counter_problems[i] > 0) {
problem_found = 1;
active_instance->counter_problems[i] -= 1;
if (active_instance->counter_problems[i] == 0) {
- sprintf (rrp_instance->status[i],
+ sprintf (rrp_instance->status[i],
"ring %d active with no faults", i);
} else {
- sprintf (rrp_instance->status[i],
+ sprintf (rrp_instance->status[i],
"Decrementing problem counter for iface %s to [%d of %d]",
totemnet_iface_print (rrp_instance->net_handles[i]),
active_instance->counter_problems[i],
rrp_instance->totem_config->rrp_problem_count_threshold);
}
log_printf (
rrp_instance->totemrrp_log_level_warning,
"%s",
rrp_instance->status[i]);
}
}
if (problem_found) {
active_timer_problem_decrementer_start (active_instance);
} else {
active_instance->timer_problem_decrementer = 0;
}
}
static void timer_function_active_token_expired (void *context)
{
struct active_instance *active_instance = (struct active_instance *)context;
struct totemrrp_instance *rrp_instance = active_instance->rrp_instance;
unsigned int i;
for (i = 0; i < rrp_instance->interface_count; i++) {
if (active_instance->last_token_recv[i] == 0) {
active_instance->counter_problems[i] += 1;
if (active_instance->timer_problem_decrementer == 0) {
active_timer_problem_decrementer_start (active_instance);
}
- sprintf (rrp_instance->status[i],
+ sprintf (rrp_instance->status[i],
"Incrementing problem counter for seqid %d iface %s to [%d of %d]",
active_instance->last_token_seq,
totemnet_iface_print (rrp_instance->net_handles[i]),
active_instance->counter_problems[i],
rrp_instance->totem_config->rrp_problem_count_threshold);
log_printf (
rrp_instance->totemrrp_log_level_warning,
"%s",
rrp_instance->status[i]);
}
}
for (i = 0; i < rrp_instance->interface_count; i++) {
if (active_instance->counter_problems[i] >= rrp_instance->totem_config->rrp_problem_count_threshold)
{
active_instance->faulty[i] = 1;
- sprintf (rrp_instance->status[i],
+ sprintf (rrp_instance->status[i],
"Marking seqid %d ringid %u interface %s FAULTY - adminisrtative intervention required.",
active_instance->last_token_seq,
i,
totemnet_iface_print (rrp_instance->net_handles[i]));
log_printf (
rrp_instance->totemrrp_log_level_error,
"%s",
rrp_instance->status[i]);
active_timer_problem_decrementer_cancel (active_instance);
}
}
rrp_instance->totemrrp_deliver_fn (
active_instance->totemrrp_context,
active_instance->token,
active_instance->token_len);
}
static void active_timer_expired_token_start (
struct active_instance *active_instance)
{
poll_timer_add (
active_instance->rrp_instance->poll_handle,
active_instance->rrp_instance->totem_config->rrp_token_expired_timeout,
(void *)active_instance,
timer_function_active_token_expired,
&active_instance->timer_expired_token);
}
static void active_timer_expired_token_cancel (
struct active_instance *active_instance)
{
poll_timer_delete (
active_instance->rrp_instance->poll_handle,
active_instance->timer_expired_token);
}
static void active_timer_problem_decrementer_start (
struct active_instance *active_instance)
{
poll_timer_add (
active_instance->rrp_instance->poll_handle,
active_instance->rrp_instance->totem_config->rrp_problem_count_timeout,
(void *)active_instance,
timer_function_active_problem_decrementer,
&active_instance->timer_problem_decrementer);
}
static void active_timer_problem_decrementer_cancel (
struct active_instance *active_instance)
{
poll_timer_delete (
active_instance->rrp_instance->poll_handle,
active_instance->timer_problem_decrementer);
}
/*
* active replication
*/
static void active_mcast_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len)
{
instance->totemrrp_deliver_fn (
context,
msg,
msg_len);
}
static void active_mcast_flush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
int i;
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_mcast_flush_send (instance->net_handles[i], iovec, iov_len);
}
}
}
static void active_mcast_noflush_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
int i;
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_mcast_noflush_send (instance->net_handles[i], iovec, iov_len);
}
}
}
static void active_token_recv (
struct totemrrp_instance *instance,
unsigned int iface_no,
void *context,
const void *msg,
size_t msg_len,
unsigned int token_seq)
{
int i;
struct active_instance *active_instance = (struct active_instance *)instance->rrp_algo_instance;
active_instance->totemrrp_context = context; // this should be in totemrrp_instance ?
if (token_seq > active_instance->last_token_seq) {
memcpy (active_instance->token, msg, msg_len);
active_instance->token_len = msg_len;
for (i = 0; i < instance->interface_count; i++) {
active_instance->last_token_recv[i] = 0;
}
active_instance->last_token_recv[iface_no] = 1;
active_timer_expired_token_start (active_instance);
}
active_instance->last_token_seq = token_seq;
if (token_seq == active_instance->last_token_seq) {
active_instance->last_token_recv[iface_no] = 1;
for (i = 0; i < instance->interface_count; i++) {
if ((active_instance->last_token_recv[i] == 0) &&
active_instance->faulty[i] == 0) {
return; /* don't deliver token */
}
}
active_timer_expired_token_cancel (active_instance);
instance->totemrrp_deliver_fn (
context,
msg,
msg_len);
}
}
static void active_token_send (
struct totemrrp_instance *instance,
const struct iovec *iovec,
unsigned int iov_len)
{
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_token_send (
instance->net_handles[i],
iovec, iov_len);
}
}
}
static void active_recv_flush (struct totemrrp_instance *instance)
{
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_recv_flush (instance->net_handles[i]);
}
}
}
static void active_send_flush (struct totemrrp_instance *instance)
{
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_send_flush (instance->net_handles[i]);
}
}
}
static void active_iface_check (struct totemrrp_instance *instance)
{
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_iface_check (instance->net_handles[i]);
}
}
}
static void active_processor_count_set (
struct totemrrp_instance *instance,
unsigned int processor_count)
{
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
unsigned int i;
for (i = 0; i < instance->interface_count; i++) {
if (rrp_algo_instance->faulty[i] == 0) {
totemnet_processor_count_set (instance->net_handles[i],
processor_count);
}
}
}
static void active_token_target_set (
struct totemrrp_instance *instance,
struct totem_ip_address *token_target,
unsigned int iface_no)
{
totemnet_token_target_set (instance->net_handles[iface_no], token_target);
}
static void active_ring_reenable (
struct totemrrp_instance *instance)
{
struct active_instance *rrp_algo_instance = (struct active_instance *)instance->rrp_algo_instance;
memset (rrp_algo_instance->last_token_recv, 0, sizeof (unsigned int) *
instance->interface_count);
memset (rrp_algo_instance->faulty, 0, sizeof (unsigned int) *
instance->interface_count);
memset (rrp_algo_instance->counter_problems, 0, sizeof (unsigned int) *
instance->interface_count);
}
struct deliver_fn_context {
struct totemrrp_instance *instance;
void *context;
int iface_no;
};
static void totemrrp_instance_initialize (struct totemrrp_instance *instance)
{
memset (instance, 0, sizeof (struct totemrrp_instance));
}
static int totemrrp_algorithm_set (
struct totem_config *totem_config,
struct totemrrp_instance *instance)
{
unsigned int res = -1;
unsigned int i;
for (i = 0; i < RRP_ALGOS_COUNT; i++) {
if (strcmp (totem_config->rrp_mode, rrp_algos[i]->name) == 0) {
instance->rrp_algo = rrp_algos[i];
if (rrp_algos[i]->initialize) {
instance->rrp_algo_instance = rrp_algos[i]->initialize (
instance,
totem_config->interface_count);
}
res = 0;
break;
}
}
for (i = 0; i < totem_config->interface_count; i++) {
instance->status[i] = malloc (1024);
sprintf (instance->status[i], "ring %d active with no faults", i);
}
return (res);
}
void rrp_deliver_fn (
void *context,
const void *msg,
size_t msg_len)
{
unsigned int token_seqid;
unsigned int token_is;
struct deliver_fn_context *deliver_fn_context = (struct deliver_fn_context *)context;
deliver_fn_context->instance->totemrrp_token_seqid_get (
msg,
&token_seqid,
&token_is);
if (token_is) {
/*
- * Deliver to the token receiver for this rrp algorithm
+ * Deliver to the token receiver for this rrp algorithm
*/
deliver_fn_context->instance->rrp_algo->token_recv (
deliver_fn_context->instance,
deliver_fn_context->iface_no,
deliver_fn_context->context,
msg,
msg_len,
token_seqid);
} else {
/*
- * Deliver to the mcast receiver for this rrp algorithm
+ * Deliver to the mcast receiver for this rrp algorithm
*/
deliver_fn_context->instance->rrp_algo->mcast_recv (
deliver_fn_context->instance,
deliver_fn_context->iface_no,
deliver_fn_context->context,
msg,
msg_len);
}
}
void rrp_iface_change_fn (
void *context,
const struct totem_ip_address *iface_addr)
{
struct deliver_fn_context *deliver_fn_context = (struct deliver_fn_context *)context;
deliver_fn_context->instance->totemrrp_iface_change_fn (
deliver_fn_context->context,
iface_addr,
deliver_fn_context->iface_no);
}
int totemrrp_finalize (
hdb_handle_t handle)
{
struct totemrrp_instance *instance;
int res = 0;
int i;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
for (i = 0; i < instance->interface_count; i++) {
totemnet_finalize (instance->net_handles[i]);
}
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
/*
* Totem Redundant Ring interface
* depends on poll abstraction, POSIX, IPV4
*/
/*
* Create an instance
*/
int totemrrp_initialize (
hdb_handle_t poll_handle,
hdb_handle_t *handle,
struct totem_config *totem_config,
void *context,
void (*deliver_fn) (
void *context,
const void *msg,
size_t msg_len),
void (*iface_change_fn) (
void *context,
const struct totem_ip_address *iface_addr,
unsigned int iface_no),
void (*token_seqid_get) (
const void *msg,
unsigned int *seqid,
unsigned int *token_is),
unsigned int (*msgs_missing) (void))
{
struct totemrrp_instance *instance;
unsigned int res;
int i;
res = hdb_handle_create (&totemrrp_instance_database,
sizeof (struct totemrrp_instance), handle);
if (res != 0) {
goto error_exit;
}
res = hdb_handle_get (&totemrrp_instance_database, *handle,
(void *)&instance);
if (res != 0) {
goto error_destroy;
}
totemrrp_instance_initialize (instance);
instance->totem_config = totem_config;
res = totemrrp_algorithm_set (
instance->totem_config,
instance);
if (res == -1) {
goto error_put;
}
/*
* Configure logging
*/
instance->totemrrp_log_level_security = totem_config->totem_logging_configuration.log_level_security;
instance->totemrrp_log_level_error = totem_config->totem_logging_configuration.log_level_error;
instance->totemrrp_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
instance->totemrrp_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
instance->totemrrp_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
instance->totemrrp_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
instance->totemrrp_log_printf = totem_config->totem_logging_configuration.log_printf;
instance->interfaces = totem_config->interfaces;
instance->totemrrp_poll_handle = poll_handle;
instance->totemrrp_deliver_fn = deliver_fn;
instance->totemrrp_iface_change_fn = iface_change_fn;
instance->totemrrp_token_seqid_get = token_seqid_get;
instance->totemrrp_msgs_missing = msgs_missing;
instance->interface_count = totem_config->interface_count;
instance->net_handles = malloc (sizeof (hdb_handle_t) * totem_config->interface_count);
instance->context = context;
instance->poll_handle = poll_handle;
for (i = 0; i < totem_config->interface_count; i++) {
struct deliver_fn_context *deliver_fn_context;
deliver_fn_context = malloc (sizeof (struct deliver_fn_context));
assert (deliver_fn_context);
deliver_fn_context->instance = instance;
deliver_fn_context->context = context;
deliver_fn_context->iface_no = i;
totemnet_initialize (
poll_handle,
&instance->net_handles[i],
totem_config,
i,
(void *)deliver_fn_context,
rrp_deliver_fn,
rrp_iface_change_fn);
}
totemnet_net_mtu_adjust (totem_config);
error_exit:
hdb_handle_put (&totemrrp_instance_database, *handle);
return (0);
error_put:
hdb_handle_put (&totemrrp_instance_database, *handle);
error_destroy:
hdb_handle_destroy (&totemrrp_instance_database, *handle);
return (res);
}
int totemrrp_processor_count_set (
hdb_handle_t handle,
unsigned int processor_count)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
instance->rrp_algo->processor_count_set (instance, processor_count);
instance->processor_count = processor_count;
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_token_target_set (
hdb_handle_t handle,
struct totem_ip_address *addr,
unsigned int iface_no)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
instance->rrp_algo->token_target_set (instance, addr, iface_no);
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_recv_flush (hdb_handle_t handle)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
instance->rrp_algo->recv_flush (instance);
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_send_flush (hdb_handle_t handle)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
instance->rrp_algo->send_flush (instance);
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_token_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
instance->rrp_algo->token_send (instance, iovec, iov_len);
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_mcast_flush_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
// TODO this needs to return the result
instance->rrp_algo->mcast_flush_send (instance, iovec, iov_len);
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_mcast_noflush_send (
hdb_handle_t handle,
const struct iovec *iovec,
unsigned int iov_len)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
/*
* merge detects go out through mcast_flush_send so it is safe to
* flush these messages if we are only one processor. This avoids
* an encryption/hmac and decryption/hmac
*/
if (instance->processor_count > 1) {
// TODO this needs to return the result
instance->rrp_algo->mcast_noflush_send (instance, iovec, iov_len);
}
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_iface_check (hdb_handle_t handle)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
instance->rrp_algo->iface_check (instance);
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_ifaces_get (
hdb_handle_t handle,
char ***status,
unsigned int *iface_count)
{
struct totemrrp_instance *instance;
int res = 0;
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
*status = instance->status;
-
+
if (iface_count) {
*iface_count = instance->interface_count;
}
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
int totemrrp_ring_reenable (
hdb_handle_t handle)
{
struct totemrrp_instance *instance;
int res = 0;
unsigned int i;
printf ("totemrrp ring reenable\n");
res = hdb_handle_get (&totemrrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
res = ENOENT;
goto error_exit;
}
-
+
instance->rrp_algo->ring_reenable (instance);
for (i = 0; i < instance->interface_count; i++) {
sprintf (instance->status[i], "ring %d active with no faults", i);
}
hdb_handle_put (&totemrrp_instance_database, handle);
error_exit:
return (res);
}
diff --git a/exec/totemsrp.c b/exec/totemsrp.c
index 42bf3f64..aef6cd21 100644
--- a/exec/totemsrp.c
+++ b/exec/totemsrp.c
@@ -1,4212 +1,4212 @@
/*
* Copyright (c) 2003-2006 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The first version of this code was based upon Yair Amir's PhD thesis:
- * http://www.cs.jhu.edu/~yairamir/phd.ps) (ch4,5).
+ * http://www.cs.jhu.edu/~yairamir/phd.ps) (ch4,5).
*
* The current version of totemsrp implements the Totem protocol specified in:
* http://citeseer.ist.psu.edu/amir95totem.html
*
* The deviations from the above published protocols are:
* - encryption of message contents with SOBER128
* - authentication of meessage contents with SHA1/HMAC
* - token hold mode where token doesn't rotate on unused ring - reduces cpu
* usage on 1.6ghz xeon from 35% to less then .1 % as measured by top
*/
#include <config.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <corosync/swab.h>
#include <corosync/queue.h>
#include <corosync/sq.h>
#include <corosync/list.h>
#include <corosync/hdb.h>
#include <corosync/totem/coropoll.h>
#include "totemsrp.h"
#include "totemrrp.h"
#include "wthread.h"
#include "crypto.h"
#define LOCALHOST_IP inet_addr("127.0.0.1")
#define QUEUE_RTR_ITEMS_SIZE_MAX 256 /* allow 256 retransmit items */
#define RETRANS_MESSAGE_QUEUE_SIZE_MAX 500 /* allow 500 messages to be queued */
#define RECEIVED_MESSAGE_QUEUE_SIZE_MAX 500 /* allow 500 messages to be queued */
-#define MAXIOVS 5
+#define MAXIOVS 5
#define RETRANSMIT_ENTRIES_MAX 30
#define TOKEN_SIZE_MAX 64000 /* bytes */
/*
* Rollover handling:
* SEQNO_START_MSG is the starting sequence number after a new configuration
* This should remain zero, unless testing overflow in which case
* 0x7ffff000 and 0xfffff000 are good starting values.
*
* SEQNO_START_TOKEN is the starting sequence number after a new configuration
* for a token. This should remain zero, unless testing overflow in which
* case 07fffff00 or 0xffffff00 are good starting values.
*
* SEQNO_START_MSG is the starting sequence number after a new configuration
* This should remain zero, unless testing overflow in which case
* 0x7ffff000 and 0xfffff000 are good values to start with
*/
#define SEQNO_START_MSG 0x0
#define SEQNO_START_TOKEN 0x0
/*
* These can be used ot test different rollover points
- * #define SEQNO_START_MSG 0xfffffe00
+ * #define SEQNO_START_MSG 0xfffffe00
* #define SEQNO_START_TOKEN 0xfffffe00
*/
/*
* These can be used to test the error recovery algorithms
* #define TEST_DROP_ORF_TOKEN_PERCENTAGE 30
* #define TEST_DROP_COMMIT_TOKEN_PERCENTAGE 30
* #define TEST_DROP_MCAST_PERCENTAGE 50
* #define TEST_RECOVERY_MSG_COUNT 300
*/
/*
* we compare incoming messages to determine if their endian is
* different - if so convert them
*
* do not change
*/
#define ENDIAN_LOCAL 0xff22
enum message_type {
MESSAGE_TYPE_ORF_TOKEN = 0, /* Ordering, Reliability, Flow (ORF) control Token */
MESSAGE_TYPE_MCAST = 1, /* ring ordered multicast message */
MESSAGE_TYPE_MEMB_MERGE_DETECT = 2, /* merge rings if there are available rings */
MESSAGE_TYPE_MEMB_JOIN = 3, /* membership join message */
MESSAGE_TYPE_MEMB_COMMIT_TOKEN = 4, /* membership commit token */
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
*/
struct srp_addr {
struct totem_ip_address addr[INTERFACE_MAX];
};
struct consensus_list_item {
struct srp_addr addr;
int set;
};
struct token_callback_instance {
struct list_head list;
int (*callback_fn) (enum totem_callback_token_type type, const void *);
enum totem_callback_token_type callback_type;
int delete;
void *data;
};
struct totemsrp_socket {
int mcast;
int token;
};
struct message_header {
char type;
char encapsulated;
unsigned short endian_detector;
unsigned int nodeid;
} __attribute__((packed));
struct mcast {
struct message_header header;
struct srp_addr system_from;
unsigned int seq;
int this_seqno;
struct memb_ring_id ring_id;
unsigned int node_id;
int guarantee;
} __attribute__((packed));
/*
* MTU - multicast message header - IP header - UDP header
*
* On lossy switches, making use of the DF UDP flag can lead to loss of
* forward progress. So the packets must be fragmented by a higher layer
*
* This layer can only handle packets of MTU size.
*/
#define FRAGMENT_SIZE (FRAME_SIZE_MAX - sizeof (struct mcast) - 20 - 8)
struct rtr_item {
struct memb_ring_id ring_id;
unsigned int seq;
}__attribute__((packed));
struct orf_token {
struct message_header header;
unsigned int seq;
unsigned int token_seq;
unsigned int aru;
unsigned int aru_addr;
- struct memb_ring_id ring_id;
+ struct memb_ring_id ring_id;
unsigned int backlog;
unsigned int fcc;
int retrans_flg;
int rtr_list_entries;
struct rtr_item rtr_list[0];
}__attribute__((packed));
struct memb_join {
struct message_header header;
struct srp_addr system_from;
unsigned int proc_list_entries;
unsigned int failed_list_entries;
unsigned long long ring_seq;
unsigned char end_of_memb_join[0];
/*
* These parts of the data structure are dynamic:
* struct srp_addr proc_list[];
* struct srp_addr failed_list[];
*/
} __attribute__((packed));
-
+
struct memb_merge_detect {
struct message_header header;
struct srp_addr system_from;
struct memb_ring_id ring_id;
} __attribute__((packed));
struct token_hold_cancel {
struct message_header header;
struct memb_ring_id ring_id;
} __attribute__((packed));
struct memb_commit_token_memb_entry {
struct memb_ring_id ring_id;
unsigned int aru;
unsigned int high_delivered;
unsigned int received_flg;
}__attribute__((packed));
struct memb_commit_token {
struct message_header header;
unsigned int token_seq;
struct memb_ring_id ring_id;
unsigned int retrans_flg;
int memb_index;
int addr_entries;
unsigned char end_of_commit_token[0];
/*
* These parts of the data structure are dynamic:
*
* struct srp_addr addr[PROCESSOR_COUNT_MAX];
* struct memb_commit_token_memb_entry memb_list[PROCESSOR_COUNT_MAX];
*/
}__attribute__((packed));
struct message_item {
struct mcast *mcast;
struct iovec iovec[MAXIOVS];
unsigned int iov_len;
};
struct sort_queue_item {
struct iovec iovec[MAXIOVS];
unsigned int iov_len;
};
struct orf_token_mcast_thread_state {
char iobuf[9000];
prng_state prng_state;
};
enum memb_state {
MEMB_STATE_OPERATIONAL = 1,
MEMB_STATE_GATHER = 2,
MEMB_STATE_COMMIT = 3,
MEMB_STATE_RECOVERY = 4
};
struct totemsrp_instance {
int iface_changes;
/*
* Flow control mcasts and remcasts on last and current orf_token
*/
int fcc_remcast_last;
int fcc_mcast_last;
int fcc_remcast_current;
struct consensus_list_item consensus_list[PROCESSOR_COUNT_MAX];
int consensus_list_entries;
struct srp_addr my_id;
struct srp_addr my_proc_list[PROCESSOR_COUNT_MAX];
struct srp_addr my_failed_list[PROCESSOR_COUNT_MAX];
struct srp_addr my_new_memb_list[PROCESSOR_COUNT_MAX];
struct srp_addr my_trans_memb_list[PROCESSOR_COUNT_MAX];
struct srp_addr my_memb_list[PROCESSOR_COUNT_MAX];
struct srp_addr my_deliver_memb_list[PROCESSOR_COUNT_MAX];
struct srp_addr my_left_memb_list[PROCESSOR_COUNT_MAX];
int my_proc_list_entries;
int my_failed_list_entries;
int my_new_memb_entries;
int my_trans_memb_entries;
int my_memb_entries;
int my_deliver_memb_entries;
int my_left_memb_entries;
struct memb_ring_id my_ring_id;
struct memb_ring_id my_old_ring_id;
int my_aru_count;
int my_merge_detect_timeout_outstanding;
unsigned int my_last_aru;
int my_seq_unchanged;
int my_received_flg;
unsigned int my_high_seq_received;
unsigned int my_install_seq;
int my_rotation_counter;
int my_set_retrans_flg;
int my_retrans_flg_count;
unsigned int my_high_ring_delivered;
-
+
int heartbeat_timeout;
/*
* Queues used to order, deliver, and recover messages
*/
struct queue new_message_queue;
struct queue retrans_message_queue;
struct sq regular_sort_queue;
struct sq recovery_sort_queue;
/*
* Received up to and including
*/
unsigned int my_aru;
unsigned int my_high_delivered;
struct list_head token_callback_received_listhead;
struct list_head token_callback_sent_listhead;
char *orf_token_retransmit[TOKEN_SIZE_MAX];
int orf_token_retransmit_size;
unsigned int my_token_seq;
/*
* Timers
*/
poll_timer_handle timer_orf_token_timeout;
poll_timer_handle timer_orf_token_retransmit_timeout;
poll_timer_handle timer_orf_token_hold_retransmit_timeout;
poll_timer_handle timer_merge_detect_timeout;
poll_timer_handle memb_timer_state_gather_join_timeout;
poll_timer_handle memb_timer_state_gather_consensus_timeout;
poll_timer_handle memb_timer_state_commit_timeout;
poll_timer_handle timer_heartbeat_timeout;
/*
* Function and data used to log messages
*/
int totemsrp_log_level_security;
int totemsrp_log_level_error;
int totemsrp_log_level_warning;
int totemsrp_log_level_notice;
int totemsrp_log_level_debug;
int totemsrp_subsys_id;
- void (*totemsrp_log_printf) (int subsys,
+ void (*totemsrp_log_printf) (int subsys,
const char *function, const char *file,
int line, unsigned int level,
const char *format, ...)__attribute__((format(printf, 6, 7)));;
enum memb_state memb_state;
//TODO struct srp_addr next_memb;
char iov_buffer[FRAME_SIZE_MAX];
struct iovec totemsrp_iov_recv;
hdb_handle_t totemsrp_poll_handle;
/*
* Function called when new message received
*/
int (*totemsrp_recv) (char *group, struct iovec *iovec, unsigned int iov_len);
struct totem_ip_address mcast_address;
void (*totemsrp_deliver_fn) (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required);
void (*totemsrp_confchg_fn) (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id);
int global_seqno;
int my_token_held;
unsigned long long token_ring_id_seq;
unsigned int last_released;
unsigned int set_aru;
int old_ring_state_saved;
int old_ring_state_aru;
unsigned int old_ring_state_high_seq_received;
int ring_saved;
unsigned int my_last_seq;
struct timeval tv_old;
hdb_handle_t totemrrp_handle;
struct totem_config *totem_config;
unsigned int use_heartbeat;
unsigned int my_trc;
unsigned int my_pbl;
unsigned int my_cbl;
};
struct message_handlers {
int count;
int (*handler_functions[6]) (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
};
/*
* forward decls
*/
static int message_handler_orf_token (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
static int message_handler_mcast (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
static int message_handler_memb_merge_detect (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
static int message_handler_memb_join (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
static int message_handler_memb_commit_token (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
static int message_handler_token_hold_cancel (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed);
static void totemsrp_instance_initialize (struct totemsrp_instance *instance);
static unsigned int main_msgs_missing (void);
static void main_token_seqid_get (
const void *msg,
unsigned int *seqid,
unsigned int *token_is);
static void srp_addr_copy (struct srp_addr *dest, const struct srp_addr *src);
static void srp_addr_to_nodeid (
unsigned int *nodeid_out,
struct srp_addr *srp_addr_in,
unsigned int entries);
static int srp_addr_equal (const struct srp_addr *a, const struct srp_addr *b);
static void memb_ring_id_create_or_load (struct totemsrp_instance *, struct memb_ring_id *);
static void token_callbacks_execute (struct totemsrp_instance *instance, enum totem_callback_token_type type);
static void memb_state_gather_enter (struct totemsrp_instance *instance, int gather_from);
static void messages_deliver_to_app (struct totemsrp_instance *instance, int skip, unsigned int end_point);
static int orf_token_mcast (struct totemsrp_instance *instance, struct orf_token *oken,
int fcc_mcasts_allowed);
static void messages_free (struct totemsrp_instance *instance, unsigned int token_aru);
static void memb_ring_id_set_and_store (struct totemsrp_instance *instance,
const 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);
static void memb_state_commit_token_create (struct totemsrp_instance *instance, struct memb_commit_token *commit_token);
static int token_hold_cancel_send (struct totemsrp_instance *instance);
static void orf_token_endian_convert (const struct orf_token *in, struct orf_token *out);
static void memb_commit_token_endian_convert (const struct memb_commit_token *in, struct memb_commit_token *out);
static void memb_join_endian_convert (const struct memb_join *in, struct memb_join *out);
static void mcast_endian_convert (const struct mcast *in, struct mcast *out);
static void memb_merge_detect_endian_convert (
const struct memb_merge_detect *in,
struct memb_merge_detect *out);
static void srp_addr_copy_endian_convert (struct srp_addr *out, const struct srp_addr *in);
static void timer_function_orf_token_timeout (void *data);
static void timer_function_heartbeat_timeout (void *data);
static void timer_function_token_retransmit_timeout (void *data);
static void timer_function_token_hold_retransmit_timeout (void *data);
static void timer_function_merge_detect_timeout (void *data);
void main_deliver_fn (
void *context,
const void *msg,
size_t msg_len);
void main_iface_change_fn (
void *context,
const struct totem_ip_address *iface_address,
unsigned int iface_no);
/*
* All instances in one database
*/
DECLARE_HDB_DATABASE (totemsrp_instance_database);
struct message_handlers totemsrp_message_handlers = {
6,
{
message_handler_orf_token,
message_handler_mcast,
message_handler_memb_merge_detect,
message_handler_memb_join,
message_handler_memb_commit_token,
message_handler_token_hold_cancel
}
};
static const char *rundir = NULL;
#define log_printf(level, format, args...) \
do { \
instance->totemsrp_log_printf (instance->totemsrp_subsys_id, \
__FUNCTION__, __FILE__, __LINE__, level, \
format, ##args); \
} while (0);
static void totemsrp_instance_initialize (struct totemsrp_instance *instance)
{
memset (instance, 0, sizeof (struct totemsrp_instance));
list_init (&instance->token_callback_received_listhead);
list_init (&instance->token_callback_sent_listhead);
instance->my_received_flg = 1;
instance->my_token_seq = SEQNO_START_TOKEN - 1;
instance->memb_state = MEMB_STATE_OPERATIONAL;
instance->set_aru = -1;
instance->my_aru = SEQNO_START_MSG;
instance->my_high_seq_received = SEQNO_START_MSG;
instance->my_high_delivered = SEQNO_START_MSG;
}
static void main_token_seqid_get (
const void *msg,
unsigned int *seqid,
unsigned int *token_is)
{
const struct orf_token *token = msg;
*seqid = 0;
*token_is = 0;
if (token->header.type == MESSAGE_TYPE_ORF_TOKEN) {
*seqid = token->token_seq;
*token_is = 1;
}
}
static unsigned int main_msgs_missing (void)
{
// TODO
return (0);
}
/*
* Exported interfaces
*/
int totemsrp_initialize (
hdb_handle_t poll_handle,
hdb_handle_t *handle,
struct totem_config *totem_config,
void (*deliver_fn) (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required),
void (*confchg_fn) (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id))
{
struct totemsrp_instance *instance;
unsigned int res;
res = hdb_handle_create (&totemsrp_instance_database,
sizeof (struct totemsrp_instance), handle);
if (res != 0) {
goto error_exit;
}
res = hdb_handle_get (&totemsrp_instance_database, *handle,
(void *)&instance);
if (res != 0) {
goto error_destroy;
}
rundir = getenv ("COROSYNC_RUN_DIR");
if (rundir == NULL) {
rundir = LOCALSTATEDIR "/lib/corosync";
}
-
+
res = mkdir (rundir, 0700);
if (res == -1 && errno != EEXIST) {
goto error_put;
}
res = chdir (rundir);
if (res == -1) {
goto error_put;
}
totemsrp_instance_initialize (instance);
instance->totem_config = totem_config;
/*
* Configure logging
*/
instance->totemsrp_log_level_security = totem_config->totem_logging_configuration.log_level_security;
instance->totemsrp_log_level_error = totem_config->totem_logging_configuration.log_level_error;
instance->totemsrp_log_level_warning = totem_config->totem_logging_configuration.log_level_warning;
instance->totemsrp_log_level_notice = totem_config->totem_logging_configuration.log_level_notice;
instance->totemsrp_log_level_debug = totem_config->totem_logging_configuration.log_level_debug;
instance->totemsrp_subsys_id = totem_config->totem_logging_configuration.log_subsys_id;
instance->totemsrp_log_printf = totem_config->totem_logging_configuration.log_printf;
/*
* Initialize local variables for totemsrp
*/
totemip_copy (&instance->mcast_address, &totem_config->interfaces[0].mcast_addr);
memset (instance->iov_buffer, 0, FRAME_SIZE_MAX);
/*
* Display totem configuration
*/
log_printf (instance->totemsrp_log_level_notice,
"Token Timeout (%d ms) retransmit timeout (%d ms)\n",
totem_config->token_timeout, totem_config->token_retransmit_timeout);
log_printf (instance->totemsrp_log_level_notice,
"token hold (%d ms) retransmits before loss (%d retrans)\n",
totem_config->token_hold_timeout, totem_config->token_retransmits_before_loss_const);
log_printf (instance->totemsrp_log_level_notice,
"join (%d ms) send_join (%d ms) consensus (%d ms) merge (%d ms)\n",
totem_config->join_timeout,
totem_config->send_join_timeout,
totem_config->consensus_timeout,
totem_config->merge_timeout);
log_printf (instance->totemsrp_log_level_notice,
"downcheck (%d ms) fail to recv const (%d msgs)\n",
totem_config->downcheck_timeout, totem_config->fail_to_recv_const);
log_printf (instance->totemsrp_log_level_notice,
"seqno unchanged const (%d rotations) Maximum network MTU %d\n", totem_config->seqno_unchanged_const, totem_config->net_mtu);
log_printf (instance->totemsrp_log_level_notice,
"window size per rotation (%d messages) maximum messages per rotation (%d messages)\n",
totem_config->window_size, totem_config->max_messages);
log_printf (instance->totemsrp_log_level_notice,
"send threads (%d threads)\n", totem_config->threads);
log_printf (instance->totemsrp_log_level_notice,
"RRP token expired timeout (%d ms)\n",
totem_config->rrp_token_expired_timeout);
log_printf (instance->totemsrp_log_level_notice,
"RRP token problem counter (%d ms)\n",
totem_config->rrp_problem_count_timeout);
log_printf (instance->totemsrp_log_level_notice,
"RRP threshold (%d problem count)\n",
totem_config->rrp_problem_count_threshold);
log_printf (instance->totemsrp_log_level_notice,
"RRP mode set to %s.\n", instance->totem_config->rrp_mode);
log_printf (instance->totemsrp_log_level_notice,
"heartbeat_failures_allowed (%d)\n", totem_config->heartbeat_failures_allowed);
log_printf (instance->totemsrp_log_level_notice,
"max_network_delay (%d ms)\n", totem_config->max_network_delay);
queue_init (&instance->retrans_message_queue, RETRANS_MESSAGE_QUEUE_SIZE_MAX,
sizeof (struct message_item));
sq_init (&instance->regular_sort_queue,
QUEUE_RTR_ITEMS_SIZE_MAX, sizeof (struct sort_queue_item), 0);
sq_init (&instance->recovery_sort_queue,
QUEUE_RTR_ITEMS_SIZE_MAX, sizeof (struct sort_queue_item), 0);
instance->totemsrp_poll_handle = poll_handle;
instance->totemsrp_deliver_fn = deliver_fn;
instance->totemsrp_confchg_fn = confchg_fn;
instance->use_heartbeat = 1;
if ( totem_config->heartbeat_failures_allowed == 0 ) {
log_printf (instance->totemsrp_log_level_notice,
"HeartBeat is Disabled. To enable set heartbeat_failures_allowed > 0\n");
instance->use_heartbeat = 0;
}
if (instance->use_heartbeat) {
- instance->heartbeat_timeout
- = (totem_config->heartbeat_failures_allowed) * totem_config->token_retransmit_timeout
+ instance->heartbeat_timeout
+ = (totem_config->heartbeat_failures_allowed) * totem_config->token_retransmit_timeout
+ totem_config->max_network_delay;
if (instance->heartbeat_timeout >= totem_config->token_timeout) {
log_printf (instance->totemsrp_log_level_notice,
- "total heartbeat_timeout (%d ms) is not less than token timeout (%d ms)\n",
+ "total heartbeat_timeout (%d ms) is not less than token timeout (%d ms)\n",
instance->heartbeat_timeout,
totem_config->token_timeout);
log_printf (instance->totemsrp_log_level_notice,
"heartbeat_timeout = heartbeat_failures_allowed * token_retransmit_timeout + max_network_delay\n");
log_printf (instance->totemsrp_log_level_notice,
"heartbeat timeout should be less than the token timeout. HeartBeat is Diabled !!\n");
instance->use_heartbeat = 0;
}
else {
log_printf (instance->totemsrp_log_level_notice,
"total heartbeat_timeout (%d ms)\n", instance->heartbeat_timeout);
}
}
-
+
totemrrp_initialize (
poll_handle,
&instance->totemrrp_handle,
totem_config,
instance,
main_deliver_fn,
main_iface_change_fn,
main_token_seqid_get,
main_msgs_missing);
/*
* Must have net_mtu adjusted by totemrrp_initialize first
*/
queue_init (&instance->new_message_queue,
MESSAGE_QUEUE_MAX,
sizeof (struct message_item));
hdb_handle_put (&totemsrp_instance_database, *handle);
return (0);
error_put:
hdb_handle_put (&totemsrp_instance_database, *handle);
error_destroy:
hdb_handle_destroy (&totemsrp_instance_database, *handle);
error_exit:
return (-1);
}
void totemsrp_finalize (
hdb_handle_t handle)
{
struct totemsrp_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
return;
}
hdb_handle_put (&totemsrp_instance_database, handle);
}
int totemsrp_ifaces_get (
hdb_handle_t handle,
unsigned int nodeid,
struct totem_ip_address *interfaces,
char ***status,
unsigned int *iface_count)
{
struct totemsrp_instance *instance;
int res;
unsigned int found = 0;
unsigned int i;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
for (i = 0; i < instance->my_memb_entries; i++) {
if (instance->my_memb_list[i].addr[0].nodeid == nodeid) {
found = 1;
break;
}
}
if (found) {
memcpy (interfaces, &instance->my_memb_list[i],
sizeof (struct srp_addr));
*iface_count = instance->totem_config->interface_count;
goto finish;
}
-
+
for (i = 0; i < instance->my_left_memb_entries; i++) {
if (instance->my_left_memb_list[i].addr[0].nodeid == nodeid) {
found = 1;
break;
}
}
if (found) {
memcpy (interfaces, &instance->my_left_memb_list[i],
sizeof (struct srp_addr));
*iface_count = instance->totem_config->interface_count;
} else {
res = -1;
}
finish:
totemrrp_ifaces_get (instance->totemrrp_handle, status, NULL);
hdb_handle_put (&totemsrp_instance_database, handle);
error_exit:
return (res);
}
unsigned int totemsrp_my_nodeid_get (
hdb_handle_t handle)
{
struct totemsrp_instance *instance;
unsigned 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 (
hdb_handle_t 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 (
hdb_handle_t handle)
{
struct totemsrp_instance *instance;
int res;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
totemrrp_ring_reenable (instance->totemrrp_handle);
hdb_handle_put (&totemsrp_instance_database, handle);
error_exit:
return (res);
}
/*
* Set operations for use by the membership algorithm
*/
static int srp_addr_equal (const struct srp_addr *a, const struct srp_addr *b)
{
unsigned int i;
unsigned int res;
for (i = 0; i < 1; i++) {
res = totemip_equal (&a->addr[i], &b->addr[i]);
if (res == 0) {
return (0);
}
}
return (1);
}
static void srp_addr_copy (struct srp_addr *dest, const struct srp_addr *src)
{
unsigned int i;
for (i = 0; i < INTERFACE_MAX; i++) {
totemip_copy (&dest->addr[i], &src->addr[i]);
}
}
static void srp_addr_to_nodeid (
unsigned int *nodeid_out,
struct srp_addr *srp_addr_in,
unsigned int entries)
{
unsigned int i;
for (i = 0; i < entries; i++) {
nodeid_out[i] = srp_addr_in[i].addr[0].nodeid;
}
}
static void srp_addr_copy_endian_convert (struct srp_addr *out, const struct srp_addr *in)
{
int i;
for (i = 0; i < INTERFACE_MAX; i++) {
totemip_copy_endian_convert (&out->addr[i], &in->addr[i]);
}
}
static void memb_consensus_reset (struct totemsrp_instance *instance)
{
instance->consensus_list_entries = 0;
}
static void memb_set_subtract (
struct srp_addr *out_list, int *out_list_entries,
struct srp_addr *one_list, int one_list_entries,
struct srp_addr *two_list, int two_list_entries)
{
int found = 0;
int i;
int j;
*out_list_entries = 0;
for (i = 0; i < one_list_entries; i++) {
for (j = 0; j < two_list_entries; j++) {
if (srp_addr_equal (&one_list[i], &two_list[j])) {
found = 1;
break;
}
}
if (found == 0) {
srp_addr_copy (&out_list[*out_list_entries], &one_list[i]);
*out_list_entries = *out_list_entries + 1;
}
found = 0;
}
}
/*
* Set consensus for a specific processor
*/
static void memb_consensus_set (
struct totemsrp_instance *instance,
const struct srp_addr *addr)
{
int found = 0;
int i;
for (i = 0; i < instance->consensus_list_entries; i++) {
if (srp_addr_equal(addr, &instance->consensus_list[i].addr)) {
found = 1;
break; /* found entry */
}
}
srp_addr_copy (&instance->consensus_list[i].addr, addr);
instance->consensus_list[i].set = 1;
if (found == 0) {
instance->consensus_list_entries++;
}
return;
}
/*
* Is consensus set for a specific processor
*/
static int memb_consensus_isset (
struct totemsrp_instance *instance,
const struct srp_addr *addr)
{
int i;
for (i = 0; i < instance->consensus_list_entries; i++) {
if (srp_addr_equal (addr, &instance->consensus_list[i].addr)) {
return (instance->consensus_list[i].set);
}
}
return (0);
}
/*
* Is consensus agreed upon based upon consensus database
*/
static int memb_consensus_agreed (
struct totemsrp_instance *instance)
{
struct srp_addr token_memb[PROCESSOR_COUNT_MAX];
int token_memb_entries = 0;
int agreed = 1;
int i;
memb_set_subtract (token_memb, &token_memb_entries,
instance->my_proc_list, instance->my_proc_list_entries,
instance->my_failed_list, instance->my_failed_list_entries);
for (i = 0; i < token_memb_entries; i++) {
if (memb_consensus_isset (instance, &token_memb[i]) == 0) {
agreed = 0;
break;
}
}
assert (token_memb_entries >= 1);
return (agreed);
}
static void memb_consensus_notset (
struct totemsrp_instance *instance,
struct srp_addr *no_consensus_list,
int *no_consensus_list_entries,
struct srp_addr *comparison_list,
int comparison_list_entries)
{
int i;
*no_consensus_list_entries = 0;
for (i = 0; i < instance->my_proc_list_entries; i++) {
if (memb_consensus_isset (instance, &instance->my_proc_list[i]) == 0) {
srp_addr_copy (&no_consensus_list[*no_consensus_list_entries], &instance->my_proc_list[i]);
*no_consensus_list_entries = *no_consensus_list_entries + 1;
}
}
}
/*
* Is set1 equal to set2 Entries can be in different orders
*/
static int memb_set_equal (
struct srp_addr *set1, int set1_entries,
struct srp_addr *set2, int set2_entries)
{
int i;
int j;
int found = 0;
if (set1_entries != set2_entries) {
return (0);
}
for (i = 0; i < set2_entries; i++) {
for (j = 0; j < set1_entries; j++) {
if (srp_addr_equal (&set1[j], &set2[i])) {
found = 1;
break;
}
}
if (found == 0) {
return (0);
}
found = 0;
}
return (1);
}
/*
* Is subset fully contained in fullset
*/
static int memb_set_subset (
const struct srp_addr *subset, int subset_entries,
const struct srp_addr *fullset, int fullset_entries)
{
int i;
int j;
int found = 0;
if (subset_entries > fullset_entries) {
return (0);
}
for (i = 0; i < subset_entries; i++) {
for (j = 0; j < fullset_entries; j++) {
if (srp_addr_equal (&subset[i], &fullset[j])) {
found = 1;
}
}
if (found == 0) {
return (0);
}
found = 0;
}
return (1);
}
/*
* merge subset into fullset taking care not to add duplicates
*/
static void memb_set_merge (
const struct srp_addr *subset, int subset_entries,
struct srp_addr *fullset, int *fullset_entries)
{
int found = 0;
int i;
int j;
for (i = 0; i < subset_entries; i++) {
for (j = 0; j < *fullset_entries; j++) {
if (srp_addr_equal (&fullset[j], &subset[i])) {
found = 1;
break;
- }
+ }
}
if (found == 0) {
srp_addr_copy (&fullset[*fullset_entries], &subset[i]);
*fullset_entries = *fullset_entries + 1;
}
found = 0;
}
return;
}
static void memb_set_and (
struct srp_addr *set1, int set1_entries,
struct srp_addr *set2, int set2_entries,
struct srp_addr *and, int *and_entries)
{
int i;
int j;
int found = 0;
*and_entries = 0;
for (i = 0; i < set2_entries; i++) {
for (j = 0; j < set1_entries; j++) {
if (srp_addr_equal (&set1[j], &set2[i])) {
found = 1;
break;
}
}
if (found) {
srp_addr_copy (&and[*and_entries], &set1[j]);
*and_entries = *and_entries + 1;
}
found = 0;
}
return;
}
#ifdef CODE_COVERAGE
static void memb_set_print (
char *string,
struct srp_addr *list,
int list_entries)
{
int i;
int j;
printf ("List '%s' contains %d entries:\n", string, list_entries);
for (i = 0; i < list_entries; i++) {
for (j = 0; j < INTERFACE_MAX; j++) {
printf ("Address %d\n", i);
printf ("\tiface %d %s\n", j, totemip_print (&list[i].addr[j]));
printf ("family %d\n", list[i].addr[j].family);
}
}
}
#endif
static void reset_token_retransmit_timeout (struct totemsrp_instance *instance)
{
poll_timer_delete (instance->totemsrp_poll_handle,
instance->timer_orf_token_retransmit_timeout);
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->token_retransmit_timeout,
(void *)instance,
timer_function_token_retransmit_timeout,
&instance->timer_orf_token_retransmit_timeout);
}
static void start_merge_detect_timeout (struct totemsrp_instance *instance)
{
if (instance->my_merge_detect_timeout_outstanding == 0) {
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->merge_timeout,
(void *)instance,
timer_function_merge_detect_timeout,
&instance->timer_merge_detect_timeout);
instance->my_merge_detect_timeout_outstanding = 1;
}
}
static void cancel_merge_detect_timeout (struct totemsrp_instance *instance)
{
poll_timer_delete (instance->totemsrp_poll_handle, instance->timer_merge_detect_timeout);
instance->my_merge_detect_timeout_outstanding = 0;
}
/*
* ring_state_* is used to save and restore the sort queue
* state when a recovery operation fails (and enters gather)
*/
static void old_ring_state_save (struct totemsrp_instance *instance)
{
if (instance->old_ring_state_saved == 0) {
instance->old_ring_state_saved = 1;
instance->old_ring_state_aru = instance->my_aru;
instance->old_ring_state_high_seq_received = instance->my_high_seq_received;
log_printf (instance->totemsrp_log_level_notice,
"Saving state aru %x high seq received %x\n",
instance->my_aru, instance->my_high_seq_received);
}
}
static void ring_save (struct totemsrp_instance *instance)
{
if (instance->ring_saved == 0) {
instance->ring_saved = 1;
memcpy (&instance->my_old_ring_id, &instance->my_ring_id,
sizeof (struct memb_ring_id));
}
}
static void ring_reset (struct totemsrp_instance *instance)
{
instance->ring_saved = 0;
}
static void ring_state_restore (struct totemsrp_instance *instance)
{
if (instance->old_ring_state_saved) {
totemip_zero_set(&instance->my_ring_id.rep);
instance->my_aru = instance->old_ring_state_aru;
instance->my_high_seq_received = instance->old_ring_state_high_seq_received;
log_printf (instance->totemsrp_log_level_notice,
"Restoring instance->my_aru %x my high seq received %x\n",
instance->my_aru, instance->my_high_seq_received);
}
}
static void old_ring_state_reset (struct totemsrp_instance *instance)
{
instance->old_ring_state_saved = 0;
}
static void reset_token_timeout (struct totemsrp_instance *instance) {
poll_timer_delete (instance->totemsrp_poll_handle, instance->timer_orf_token_timeout);
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->token_timeout,
(void *)instance,
timer_function_orf_token_timeout,
&instance->timer_orf_token_timeout);
}
static void reset_heartbeat_timeout (struct totemsrp_instance *instance) {
poll_timer_delete (instance->totemsrp_poll_handle, instance->timer_heartbeat_timeout);
poll_timer_add (instance->totemsrp_poll_handle,
instance->heartbeat_timeout,
(void *)instance,
timer_function_heartbeat_timeout,
&instance->timer_heartbeat_timeout);
}
static void cancel_token_timeout (struct totemsrp_instance *instance) {
poll_timer_delete (instance->totemsrp_poll_handle, instance->timer_orf_token_timeout);
}
static void cancel_heartbeat_timeout (struct totemsrp_instance *instance) {
poll_timer_delete (instance->totemsrp_poll_handle, instance->timer_heartbeat_timeout);
}
static void cancel_token_retransmit_timeout (struct totemsrp_instance *instance)
{
poll_timer_delete (instance->totemsrp_poll_handle, instance->timer_orf_token_retransmit_timeout);
}
static void start_token_hold_retransmit_timeout (struct totemsrp_instance *instance)
{
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->token_hold_timeout,
(void *)instance,
timer_function_token_hold_retransmit_timeout,
&instance->timer_orf_token_hold_retransmit_timeout);
}
static void cancel_token_hold_retransmit_timeout (struct totemsrp_instance *instance)
{
poll_timer_delete (instance->totemsrp_poll_handle,
instance->timer_orf_token_hold_retransmit_timeout);
}
static void memb_state_consensus_timeout_expired (
struct totemsrp_instance *instance)
{
struct srp_addr no_consensus_list[PROCESSOR_COUNT_MAX];
int no_consensus_list_entries;
if (memb_consensus_agreed (instance)) {
memb_consensus_reset (instance);
memb_consensus_set (instance, &instance->my_id);
reset_token_timeout (instance); // REVIEWED
} else {
memb_consensus_notset (
instance,
no_consensus_list,
&no_consensus_list_entries,
instance->my_proc_list,
instance->my_proc_list_entries);
memb_set_merge (no_consensus_list, no_consensus_list_entries,
instance->my_failed_list, &instance->my_failed_list_entries);
memb_state_gather_enter (instance, 0);
}
}
static void memb_join_message_send (struct totemsrp_instance *instance);
static void memb_merge_detect_transmit (struct totemsrp_instance *instance);
/*
* Timers used for various states of the membership algorithm
*/
static void timer_function_orf_token_timeout (void *data)
{
struct totemsrp_instance *instance = data;
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
log_printf (instance->totemsrp_log_level_notice,
"The token was lost in the OPERATIONAL state.\n");
totemrrp_iface_check (instance->totemrrp_handle);
memb_state_gather_enter (instance, 2);
break;
case MEMB_STATE_GATHER:
log_printf (instance->totemsrp_log_level_notice,
"The consensus timeout expired.\n");
memb_state_consensus_timeout_expired (instance);
memb_state_gather_enter (instance, 3);
break;
case MEMB_STATE_COMMIT:
log_printf (instance->totemsrp_log_level_notice,
"The token was lost in the COMMIT state.\n");
memb_state_gather_enter (instance, 4);
break;
-
+
case MEMB_STATE_RECOVERY:
log_printf (instance->totemsrp_log_level_notice,
"The token was lost in the RECOVERY state.\n");
ring_state_restore (instance);
memb_state_gather_enter (instance, 5);
break;
}
}
static void timer_function_heartbeat_timeout (void *data)
{
struct totemsrp_instance *instance = data;
log_printf (instance->totemsrp_log_level_notice,
"HeartBeat Timer expired Invoking token loss mechanism in state %d \n", instance->memb_state);
timer_function_orf_token_timeout(data);
}
static void memb_timer_function_state_gather (void *data)
{
struct totemsrp_instance *instance = data;
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
case MEMB_STATE_RECOVERY:
assert (0); /* this should never happen */
break;
case MEMB_STATE_GATHER:
case MEMB_STATE_COMMIT:
memb_join_message_send (instance);
/*
* Restart the join timeout
`*/
poll_timer_delete (instance->totemsrp_poll_handle, instance->memb_timer_state_gather_join_timeout);
-
+
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->join_timeout,
(void *)instance,
memb_timer_function_state_gather,
&instance->memb_timer_state_gather_join_timeout);
break;
}
}
static void memb_timer_function_gather_consensus_timeout (void *data)
{
struct totemsrp_instance *instance = data;
memb_state_consensus_timeout_expired (instance);
}
static void deliver_messages_from_recovery_to_regular (struct totemsrp_instance *instance)
{
unsigned int i;
struct sort_queue_item *recovery_message_item;
struct sort_queue_item regular_message_item;
unsigned int range = 0;
int res;
void *ptr;
struct mcast *mcast;
log_printf (instance->totemsrp_log_level_debug,
"recovery to regular %x-%x\n", SEQNO_START_MSG + 1, instance->my_aru);
range = instance->my_aru - SEQNO_START_MSG;
/*
* Move messages from recovery to regular sort queue
*/
// todo should i be initialized to 0 or 1 ?
for (i = 1; i <= range; i++) {
res = sq_item_get (&instance->recovery_sort_queue,
i + SEQNO_START_MSG, &ptr);
if (res != 0) {
continue;
}
recovery_message_item = ptr;
/*
* Convert recovery message into regular message
*/
if (recovery_message_item->iov_len > 1) {
mcast = recovery_message_item->iovec[1].iov_base;
memcpy (&regular_message_item.iovec[0],
&recovery_message_item->iovec[1],
sizeof (struct iovec) * recovery_message_item->iov_len);
} else {
mcast = recovery_message_item->iovec[0].iov_base;
if (mcast->header.encapsulated == MESSAGE_ENCAPSULATED) {
/*
* Message is a recovery message encapsulated
* in a new ring message
*/
regular_message_item.iovec[0].iov_base =
(char *)recovery_message_item->iovec[0].iov_base + sizeof (struct mcast);
regular_message_item.iovec[0].iov_len =
recovery_message_item->iovec[0].iov_len - sizeof (struct mcast);
regular_message_item.iov_len = 1;
mcast = regular_message_item.iovec[0].iov_base;
} else {
continue; /* TODO this case shouldn't happen */
/*
* Message is originated on new ring and not
* encapsulated
*/
regular_message_item.iovec[0].iov_base =
recovery_message_item->iovec[0].iov_base;
regular_message_item.iovec[0].iov_len =
recovery_message_item->iovec[0].iov_len;
}
}
log_printf (instance->totemsrp_log_level_debug,
"comparing if ring id is for this processors old ring seqno %d\n",
mcast->seq);
/*
* Only add this message to the regular sort
* queue if it was originated with the same ring
* id as the previous ring
*/
if (memcmp (&instance->my_old_ring_id, &mcast->ring_id,
sizeof (struct memb_ring_id)) == 0) {
regular_message_item.iov_len = recovery_message_item->iov_len;
res = sq_item_inuse (&instance->regular_sort_queue, mcast->seq);
if (res == 0) {
sq_item_add (&instance->regular_sort_queue,
&regular_message_item, mcast->seq);
if (sq_lt_compare (instance->old_ring_state_high_seq_received, mcast->seq)) {
instance->old_ring_state_high_seq_received = mcast->seq;
}
}
} else {
log_printf (instance->totemsrp_log_level_notice,
"-not adding msg with seq no %x\n", mcast->seq);
}
}
}
/*
* Change states in the state machine of the membership algorithm
*/
static void memb_state_operational_enter (struct totemsrp_instance *instance)
{
struct srp_addr joined_list[PROCESSOR_COUNT_MAX];
int joined_list_entries = 0;
unsigned int aru_save;
unsigned int joined_list_totemip[PROCESSOR_COUNT_MAX];
unsigned int trans_memb_list_totemip[PROCESSOR_COUNT_MAX];
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);
log_printf (instance->totemsrp_log_level_debug,
"Delivering to app %x to %x\n",
instance->my_high_delivered + 1, instance->old_ring_state_high_seq_received);
aru_save = instance->my_aru;
instance->my_aru = instance->old_ring_state_aru;
messages_deliver_to_app (instance, 0, instance->old_ring_state_high_seq_received);
/*
* Calculate joined and left list
*/
memb_set_subtract (instance->my_left_memb_list,
&instance->my_left_memb_entries,
instance->my_memb_list, instance->my_memb_entries,
instance->my_trans_memb_list, instance->my_trans_memb_entries);
memb_set_subtract (joined_list, &joined_list_entries,
instance->my_new_memb_list, instance->my_new_memb_entries,
instance->my_trans_memb_list, instance->my_trans_memb_entries);
/*
* Install new membership
*/
instance->my_memb_entries = instance->my_new_memb_entries;
memcpy (&instance->my_memb_list, instance->my_new_memb_list,
sizeof (struct srp_addr) * instance->my_memb_entries);
instance->last_released = 0;
instance->my_set_retrans_flg = 0;
/*
* Deliver transitional configuration to application
*/
srp_addr_to_nodeid (left_list, instance->my_left_memb_list,
instance->my_left_memb_entries);
srp_addr_to_nodeid (trans_memb_list_totemip,
instance->my_trans_memb_list, instance->my_trans_memb_entries);
instance->totemsrp_confchg_fn (TOTEM_CONFIGURATION_TRANSITIONAL,
trans_memb_list_totemip, instance->my_trans_memb_entries,
left_list, instance->my_left_memb_entries,
0, 0, &instance->my_ring_id);
-
+
// TODO we need to filter to ensure we only deliver those
// messages which are part of instance->my_deliver_memb
messages_deliver_to_app (instance, 1, instance->old_ring_state_high_seq_received);
instance->my_aru = aru_save;
/*
* Deliver regular configuration to application
*/
srp_addr_to_nodeid (new_memb_list_totemip,
instance->my_new_memb_list, instance->my_new_memb_entries);
srp_addr_to_nodeid (joined_list_totemip, joined_list,
joined_list_entries);
instance->totemsrp_confchg_fn (TOTEM_CONFIGURATION_REGULAR,
new_memb_list_totemip, instance->my_new_memb_entries,
0, 0,
joined_list_totemip, joined_list_entries, &instance->my_ring_id);
/*
* The recovery sort queue now becomes the regular
* sort queue. It is necessary to copy the state
* into the regular sort queue.
*/
sq_copy (&instance->regular_sort_queue, &instance->recovery_sort_queue);
instance->my_last_aru = SEQNO_START_MSG;
sq_items_release (&instance->regular_sort_queue, SEQNO_START_MSG - 1);
/* When making my_proc_list smaller, ensure that the
* now non-used entries are zero-ed out. There are some suspect
* assert's that assume that there is always 2 entries in the list.
* These fail when my_proc_list is reduced to 1 entry (and the
* valid [0] entry is the same as the 'unused' [1] entry).
*/
memset(instance->my_proc_list, 0,
sizeof (struct srp_addr) * instance->my_proc_list_entries);
instance->my_proc_list_entries = instance->my_new_memb_entries;
memcpy (instance->my_proc_list, instance->my_new_memb_list,
sizeof (struct srp_addr) * instance->my_memb_entries);
instance->my_failed_list_entries = 0;
instance->my_high_delivered = instance->my_aru;
// TODO the recovery messages are leaked
log_printf (instance->totemsrp_log_level_notice,
"entering OPERATIONAL state.\n");
instance->memb_state = MEMB_STATE_OPERATIONAL;
instance->my_received_flg = 1;
return;
}
static void memb_state_gather_enter (
struct totemsrp_instance *instance,
int gather_from)
{
memb_set_merge (
&instance->my_id, 1,
instance->my_proc_list, &instance->my_proc_list_entries);
assert (srp_addr_equal (&instance->my_proc_list[0], &instance->my_proc_list[1]) == 0);
memb_join_message_send (instance);
/*
* Restart the join timeout
*/
poll_timer_delete (instance->totemsrp_poll_handle, instance->memb_timer_state_gather_join_timeout);
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->join_timeout,
(void *)instance,
memb_timer_function_state_gather,
&instance->memb_timer_state_gather_join_timeout);
/*
* Restart the consensus timeout
*/
poll_timer_delete (instance->totemsrp_poll_handle,
instance->memb_timer_state_gather_consensus_timeout);
poll_timer_add (instance->totemsrp_poll_handle,
instance->totem_config->consensus_timeout,
(void *)instance,
memb_timer_function_gather_consensus_timeout,
&instance->memb_timer_state_gather_consensus_timeout);
/*
* Cancel the token loss and token retransmission timeouts
*/
cancel_token_retransmit_timeout (instance); // REVIEWED
cancel_token_timeout (instance); // REVIEWED
cancel_merge_detect_timeout (instance);
memb_consensus_reset (instance);
memb_consensus_set (instance, &instance->my_id);
log_printf (instance->totemsrp_log_level_notice,
"entering GATHER state from %d.\n", gather_from);
instance->memb_state = MEMB_STATE_GATHER;
return;
}
static void timer_function_token_retransmit_timeout (void *data);
static void memb_state_commit_enter (
struct totemsrp_instance *instance,
struct memb_commit_token *commit_token)
{
ring_save (instance);
- old_ring_state_save (instance);
+ old_ring_state_save (instance);
memb_state_commit_token_update (instance, commit_token);
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);
instance->token_ring_id_seq = instance->my_ring_id.seq;
poll_timer_delete (instance->totemsrp_poll_handle, instance->memb_timer_state_gather_join_timeout);
instance->memb_timer_state_gather_join_timeout = 0;
poll_timer_delete (instance->totemsrp_poll_handle, instance->memb_timer_state_gather_consensus_timeout);
instance->memb_timer_state_gather_consensus_timeout = 0;
reset_token_timeout (instance); // REVIEWED
reset_token_retransmit_timeout (instance); // REVIEWED
log_printf (instance->totemsrp_log_level_notice,
"entering COMMIT state.\n");
instance->memb_state = MEMB_STATE_COMMIT;
/*
* reset all flow control variables since we are starting a new ring
*/
instance->my_trc = 0;
instance->my_pbl = 0;
instance->my_cbl = 0;
return;
}
static void memb_state_recovery_enter (
struct totemsrp_instance *instance,
struct memb_commit_token *commit_token)
{
int i;
int local_received_flg = 1;
unsigned int low_ring_aru;
unsigned int range = 0;
unsigned int messages_originated = 0;
char is_originated[4096];
char not_originated[4096];
char seqno_string_hex[10];
const struct srp_addr *addr;
struct memb_commit_token_memb_entry *memb_list;
addr = (const struct srp_addr *)commit_token->end_of_commit_token;
memb_list = (struct memb_commit_token_memb_entry *)(addr + commit_token->addr_entries);
log_printf (instance->totemsrp_log_level_notice,
"entering RECOVERY state.\n");
instance->my_high_ring_delivered = 0;
sq_reinit (&instance->recovery_sort_queue, SEQNO_START_MSG);
queue_reinit (&instance->retrans_message_queue);
low_ring_aru = instance->old_ring_state_high_seq_received;
memb_state_commit_token_send (instance, commit_token);
instance->my_token_seq = SEQNO_START_TOKEN - 1;
/*
* Build regular configuration
*/
totemrrp_processor_count_set (
instance->totemrrp_handle,
commit_token->addr_entries);
/*
* Build transitional configuration
*/
memb_set_and (instance->my_new_memb_list, instance->my_new_memb_entries,
instance->my_memb_list, instance->my_memb_entries,
instance->my_trans_memb_list, &instance->my_trans_memb_entries);
for (i = 0; i < instance->my_new_memb_entries; i++) {
log_printf (instance->totemsrp_log_level_notice,
"position [%d] member %s:\n", i, totemip_print (&addr[i].addr[0]));
log_printf (instance->totemsrp_log_level_notice,
"previous ring seq %lld rep %s\n",
memb_list[i].ring_id.seq,
totemip_print (&memb_list[i].ring_id.rep));
log_printf (instance->totemsrp_log_level_notice,
"aru %x high delivered %x received flag %d\n",
memb_list[i].aru,
memb_list[i].high_delivered,
memb_list[i].received_flg);
// assert (totemip_print (&memb_list[i].ring_id.rep) != 0);
}
/*
* Determine if any received flag is false
*/
for (i = 0; i < commit_token->addr_entries; i++) {
if (memb_set_subset (&instance->my_new_memb_list[i], 1,
instance->my_trans_memb_list, instance->my_trans_memb_entries) &&
memb_list[i].received_flg == 0) {
instance->my_deliver_memb_entries = instance->my_trans_memb_entries;
memcpy (instance->my_deliver_memb_list, instance->my_trans_memb_list,
sizeof (struct srp_addr) * instance->my_trans_memb_entries);
local_received_flg = 0;
break;
}
}
if (local_received_flg == 1) {
goto no_originate;
} /* Else originate messages if we should */
/*
* Calculate my_low_ring_aru, instance->my_high_ring_delivered for the transitional membership
*/
for (i = 0; i < commit_token->addr_entries; i++) {
if (memb_set_subset (&instance->my_new_memb_list[i], 1,
instance->my_deliver_memb_list,
instance->my_deliver_memb_entries) &&
memcmp (&instance->my_old_ring_id,
&memb_list[i].ring_id,
sizeof (struct memb_ring_id)) == 0) {
if (sq_lt_compare (memb_list[i].aru, low_ring_aru)) {
low_ring_aru = memb_list[i].aru;
}
if (sq_lt_compare (instance->my_high_ring_delivered, memb_list[i].high_delivered)) {
instance->my_high_ring_delivered = memb_list[i].high_delivered;
}
}
}
/*
* Copy all old ring messages to instance->retrans_message_queue
*/
range = instance->old_ring_state_high_seq_received - low_ring_aru;
if (range == 0) {
/*
* No messages to copy
*/
goto no_originate;
}
assert (range < 1024);
log_printf (instance->totemsrp_log_level_notice,
"copying all old ring messages from %x-%x.\n",
low_ring_aru + 1, instance->old_ring_state_high_seq_received);
strcpy (not_originated, "Not Originated for recovery: ");
strcpy (is_originated, "Originated for recovery: ");
-
+
for (i = 1; i <= range; i++) {
struct sort_queue_item *sort_queue_item;
struct message_item message_item;
void *ptr;
int res;
sprintf (seqno_string_hex, "%x ", low_ring_aru + i);
res = sq_item_get (&instance->regular_sort_queue,
low_ring_aru + i, &ptr);
if (res != 0) {
strcat (not_originated, seqno_string_hex);
continue;
}
strcat (is_originated, seqno_string_hex);
sort_queue_item = ptr;
assert (sort_queue_item->iov_len > 0);
assert (sort_queue_item->iov_len <= MAXIOVS);
messages_originated++;
memset (&message_item, 0, sizeof (struct message_item));
// TODO LEAK
message_item.mcast = malloc (sizeof (struct mcast));
assert (message_item.mcast);
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);
queue_item_add (&instance->retrans_message_queue, &message_item);
}
log_printf (instance->totemsrp_log_level_notice,
"Originated %d messages in RECOVERY.\n", messages_originated);
strcat (not_originated, "\n");
strcat (is_originated, "\n");
log_printf (instance->totemsrp_log_level_notice, "%s", is_originated);
log_printf (instance->totemsrp_log_level_notice, "%s", not_originated);
goto originated;
no_originate:
log_printf (instance->totemsrp_log_level_notice,
"Did not need to originate any messages in recovery.\n");
originated:
instance->my_aru = SEQNO_START_MSG;
instance->my_aru_count = 0;
instance->my_seq_unchanged = 0;
instance->my_high_seq_received = SEQNO_START_MSG;
instance->my_install_seq = SEQNO_START_MSG;
instance->last_released = SEQNO_START_MSG;
reset_token_timeout (instance); // REVIEWED
reset_token_retransmit_timeout (instance); // REVIEWED
instance->memb_state = MEMB_STATE_RECOVERY;
return;
}
int totemsrp_new_msg_signal (hdb_handle_t handle)
{
struct totemsrp_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
token_hold_cancel_send (instance);
hdb_handle_put (&totemsrp_instance_database, handle);
return (0);
error_exit:
return (-1);
}
int totemsrp_mcast (
hdb_handle_t handle,
struct iovec *iovec,
unsigned int iov_len,
int guarantee)
{
int i;
int j;
struct message_item message_item;
struct totemsrp_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
-
+
if (queue_is_full (&instance->new_message_queue)) {
log_printf (instance->totemsrp_log_level_warning, "queue full\n");
return (-1);
}
for (j = 0, i = 0; i < iov_len; i++) {
j+= iovec[i].iov_len;
}
memset (&message_item, 0, sizeof (struct message_item));
/*
* Allocate pending item
*/
// TODO LEAK
message_item.mcast = malloc (sizeof (struct mcast));
if (message_item.mcast == 0) {
goto error_mcast;
}
/*
* Set mcast header
*/
message_item.mcast->header.type = MESSAGE_TYPE_MCAST;
message_item.mcast->header.endian_detector = ENDIAN_LOCAL;
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);
message_item.mcast->guarantee = guarantee;
srp_addr_copy (&message_item.mcast->system_from, &instance->my_id);
for (i = 0; i < iov_len; i++) {
// TODO LEAK
message_item.iovec[i].iov_base = malloc (iovec[i].iov_len);
if (message_item.iovec[i].iov_base == 0) {
goto error_iovec;
}
memcpy (message_item.iovec[i].iov_base, iovec[i].iov_base,
iovec[i].iov_len);
message_item.iovec[i].iov_len = iovec[i].iov_len;
}
message_item.iov_len = iov_len;
log_printf (instance->totemsrp_log_level_debug, "mcasted message added to pending queue\n");
queue_item_add (&instance->new_message_queue, &message_item);
hdb_handle_put (&totemsrp_instance_database, handle);
return (0);
error_iovec:
for (j = 0; j < i; j++) {
free (message_item.iovec[j].iov_base);
}
-
+
free(message_item.mcast);
error_mcast:
hdb_handle_put (&totemsrp_instance_database, handle);
error_exit:
return (-1);
}
/*
* Determine if there is room to queue a new message
*/
int totemsrp_avail (hdb_handle_t handle)
{
int avail;
struct totemsrp_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
queue_avail (&instance->new_message_queue, &avail);
hdb_handle_put (&totemsrp_instance_database, handle);
return (avail);
error_exit:
return (0);
}
/*
* ORF Token Management
*/
-/*
+/*
* Recast message to mcast group if it is available
*/
static int orf_token_remcast (
struct totemsrp_instance *instance,
int seq)
{
struct sort_queue_item *sort_queue_item;
int res;
void *ptr;
struct sq *sort_queue;
if (instance->memb_state == MEMB_STATE_RECOVERY) {
sort_queue = &instance->recovery_sort_queue;
} else {
sort_queue = &instance->regular_sort_queue;
}
res = sq_in_range (sort_queue, seq);
if (res == 0) {
log_printf (instance->totemsrp_log_level_debug, "sq not in range\n");
return (-1);
}
-
+
/*
* Get RTR item at seq, if not available, return
*/
res = sq_item_get (sort_queue, seq, &ptr);
if (res != 0) {
return -1;
}
sort_queue_item = ptr;
totemrrp_mcast_noflush_send (instance->totemrrp_handle,
sort_queue_item->iovec,
sort_queue_item->iov_len);
return (0);
}
/*
* Free all freeable messages from ring
*/
static void messages_free (
struct totemsrp_instance *instance,
unsigned int token_aru)
{
struct sort_queue_item *regular_message;
unsigned int i, j;
int res;
int log_release = 0;
unsigned int release_to;
unsigned int range = 0;
release_to = token_aru;
if (sq_lt_compare (instance->my_last_aru, release_to)) {
release_to = instance->my_last_aru;
}
if (sq_lt_compare (instance->my_high_delivered, release_to)) {
release_to = instance->my_high_delivered;
}
/*
* Ensure we dont try release before an already released point
*/
if (sq_lt_compare (release_to, instance->last_released)) {
return;
}
range = release_to - instance->last_released;
assert (range < 1024);
/*
* Release retransmit list items if group aru indicates they are transmitted
*/
for (i = 1; i <= range; i++) {
void *ptr;
res = sq_item_get (&instance->regular_sort_queue,
instance->last_released + i, &ptr);
if (res == 0) {
regular_message = ptr;
for (j = 0; j < regular_message->iov_len; j++) {
free (regular_message->iovec[j].iov_base);
}
}
sq_items_release (&instance->regular_sort_queue,
instance->last_released + i);
log_release = 1;
}
instance->last_released += range;
if (log_release) {
log_printf (instance->totemsrp_log_level_debug,
"releasing messages up to and including %x\n", release_to);
}
}
static void update_aru (
struct totemsrp_instance *instance)
{
unsigned int i;
int res;
struct sq *sort_queue;
unsigned int range;
unsigned int my_aru_saved = 0;
if (instance->memb_state == MEMB_STATE_RECOVERY) {
sort_queue = &instance->recovery_sort_queue;
} else {
sort_queue = &instance->regular_sort_queue;
}
range = instance->my_high_seq_received - instance->my_aru;
if (range > 1024) {
return;
}
my_aru_saved = instance->my_aru;
for (i = 1; i <= range; i++) {
void *ptr;
res = sq_item_get (sort_queue, my_aru_saved + i, &ptr);
/*
* If hole, stop updating aru
*/
if (res != 0) {
break;
}
}
instance->my_aru += i - 1;
}
/*
* Multicasts pending messages onto the ring (requires orf_token possession)
*/
static int orf_token_mcast (
struct totemsrp_instance *instance,
struct orf_token *token,
int fcc_mcasts_allowed)
{
struct message_item *message_item = 0;
struct queue *mcast_queue;
struct sq *sort_queue;
struct sort_queue_item sort_queue_item;
struct sort_queue_item *sort_queue_item_ptr;
struct mcast *mcast;
unsigned int fcc_mcast_current;
if (instance->memb_state == MEMB_STATE_RECOVERY) {
mcast_queue = &instance->retrans_message_queue;
sort_queue = &instance->recovery_sort_queue;
reset_token_retransmit_timeout (instance); // REVIEWED
} else {
mcast_queue = &instance->new_message_queue;
sort_queue = &instance->regular_sort_queue;
}
for (fcc_mcast_current = 0; fcc_mcast_current < fcc_mcasts_allowed; fcc_mcast_current++) {
if (queue_is_empty (mcast_queue)) {
break;
}
message_item = (struct message_item *)queue_item_get (mcast_queue);
/* preincrement required by algo */
if (instance->old_ring_state_saved &&
(instance->memb_state == MEMB_STATE_GATHER ||
instance->memb_state == MEMB_STATE_COMMIT)) {
log_printf (instance->totemsrp_log_level_debug,
"not multicasting at seqno is %d\n",
token->seq);
return (0);
}
message_item->mcast->seq = ++token->seq;
message_item->mcast->this_seqno = instance->global_seqno++;
/*
* Build IO vector
*/
memset (&sort_queue_item, 0, sizeof (struct sort_queue_item));
sort_queue_item.iovec[0].iov_base = message_item->mcast;
sort_queue_item.iovec[0].iov_len = sizeof (struct mcast);
-
+
mcast = sort_queue_item.iovec[0].iov_base;
-
+
memcpy (&sort_queue_item.iovec[1], message_item->iovec,
message_item->iov_len * sizeof (struct iovec));
memcpy (&mcast->ring_id, &instance->my_ring_id, sizeof (struct memb_ring_id));
sort_queue_item.iov_len = message_item->iov_len + 1;
assert (sort_queue_item.iov_len < 16);
/*
* Add message to retransmit queue
*/
sort_queue_item_ptr = sq_item_add (sort_queue,
&sort_queue_item, message_item->mcast->seq);
totemrrp_mcast_noflush_send (instance->totemrrp_handle,
sort_queue_item_ptr->iovec,
sort_queue_item_ptr->iov_len);
-
+
/*
* 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;
}
update_aru (instance);
/*
* Return 1 if more messages are available for single node clusters
*/
return (fcc_mcast_current);
}
/*
* Remulticasts messages in orf_token's retransmit list (requires orf_token)
* Modify's orf_token's rtr to include retransmits required by this process
*/
static int orf_token_rtr (
struct totemsrp_instance *instance,
struct orf_token *orf_token,
unsigned int *fcc_allowed)
{
unsigned int res;
unsigned int i, j;
unsigned int found;
unsigned int total_entries;
struct sq *sort_queue;
struct rtr_item *rtr_list;
unsigned int range = 0;
char retransmit_msg[1024];
char value[64];
if (instance->memb_state == MEMB_STATE_RECOVERY) {
sort_queue = &instance->recovery_sort_queue;
} else {
sort_queue = &instance->regular_sort_queue;
}
rtr_list = &orf_token->rtr_list[0];
-
+
strcpy (retransmit_msg, "Retransmit List: ");
if (orf_token->rtr_list_entries) {
log_printf (instance->totemsrp_log_level_debug,
"Retransmit List %d\n", orf_token->rtr_list_entries);
for (i = 0; i < orf_token->rtr_list_entries; i++) {
sprintf (value, "%x ", rtr_list[i].seq);
strcat (retransmit_msg, value);
}
strcat (retransmit_msg, "\n");
log_printf (instance->totemsrp_log_level_notice,
"%s", retransmit_msg);
}
total_entries = orf_token->rtr_list_entries;
/*
* Retransmit messages on orf_token's RTR list from RTR queue
*/
for (instance->fcc_remcast_current = 0, i = 0;
instance->fcc_remcast_current < *fcc_allowed && i < orf_token->rtr_list_entries;) {
/*
* If this retransmit request isn't from this configuration,
* try next rtr entry
*/
if (memcmp (&rtr_list[i].ring_id, &instance->my_ring_id,
sizeof (struct memb_ring_id)) != 0) {
i += 1;
continue;
}
res = orf_token_remcast (instance, rtr_list[i].seq);
if (res == 0) {
/*
* Multicasted message, so no need to copy to new retransmit list
*/
orf_token->rtr_list_entries -= 1;
assert (orf_token->rtr_list_entries >= 0);
memmove (&rtr_list[i], &rtr_list[i + 1],
sizeof (struct rtr_item) * (orf_token->rtr_list_entries));
instance->fcc_remcast_current++;
} else {
i += 1;
}
}
*fcc_allowed = *fcc_allowed - instance->fcc_remcast_current;
/*
* Add messages to retransmit to RTR list
* but only retry if there is room in the retransmit list
*/
range = instance->my_high_seq_received - instance->my_aru;
assert (range < 100000);
for (i = 1; (orf_token->rtr_list_entries < RETRANSMIT_ENTRIES_MAX) &&
(i <= range); i++) {
/*
* Ensure message is within the sort queue range
*/
res = sq_in_range (sort_queue, instance->my_aru + i);
if (res == 0) {
break;
}
/*
* Find if a message is missing from this processor
*/
res = sq_item_inuse (sort_queue, instance->my_aru + i);
if (res == 0) {
/*
* Determine if missing message is already in retransmit list
*/
found = 0;
for (j = 0; j < orf_token->rtr_list_entries; j++) {
if (instance->my_aru + i == rtr_list[j].seq) {
found = 1;
}
}
if (found == 0) {
/*
* Missing message not found in current retransmit list so add it
*/
memcpy (&rtr_list[orf_token->rtr_list_entries].ring_id,
&instance->my_ring_id, sizeof (struct memb_ring_id));
rtr_list[orf_token->rtr_list_entries].seq = instance->my_aru + i;
orf_token->rtr_list_entries++;
}
}
}
return (instance->fcc_remcast_current);
}
static void token_retransmit (struct totemsrp_instance *instance)
{
struct iovec iovec;
iovec.iov_base = instance->orf_token_retransmit;
iovec.iov_len = instance->orf_token_retransmit_size;
totemrrp_token_send (instance->totemrrp_handle,
&iovec,
1);
}
/*
* Retransmit the regular token if no mcast or token has
* been received in retransmit token period retransmit
* the token to the next processor
*/
static void timer_function_token_retransmit_timeout (void *data)
{
struct totemsrp_instance *instance = data;
switch (instance->memb_state) {
case MEMB_STATE_GATHER:
break;
case MEMB_STATE_COMMIT:
case MEMB_STATE_OPERATIONAL:
case MEMB_STATE_RECOVERY:
token_retransmit (instance);
reset_token_retransmit_timeout (instance); // REVIEWED
break;
}
}
static void timer_function_token_hold_retransmit_timeout (void *data)
{
struct totemsrp_instance *instance = data;
switch (instance->memb_state) {
case MEMB_STATE_GATHER:
break;
case MEMB_STATE_COMMIT:
break;
case MEMB_STATE_OPERATIONAL:
case MEMB_STATE_RECOVERY:
token_retransmit (instance);
break;
}
}
static void timer_function_merge_detect_timeout(void *data)
{
struct totemsrp_instance *instance = data;
instance->my_merge_detect_timeout_outstanding = 0;
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
if (totemip_equal(&instance->my_ring_id.rep, &instance->my_id.addr[0])) {
memb_merge_detect_transmit (instance);
}
break;
case MEMB_STATE_GATHER:
case MEMB_STATE_COMMIT:
case MEMB_STATE_RECOVERY:
break;
}
}
/*
* Send orf_token to next member (requires orf_token)
*/
static int token_send (
struct totemsrp_instance *instance,
struct orf_token *orf_token,
int forward_token)
{
struct iovec iovec;
int res = 0;
unsigned int iov_len = sizeof (struct orf_token) +
(orf_token->rtr_list_entries * sizeof (struct rtr_item));
memcpy (instance->orf_token_retransmit, orf_token, iov_len);
instance->orf_token_retransmit_size = iov_len;
orf_token->header.nodeid = instance->my_id.addr[0].nodeid;
assert (orf_token->header.nodeid);
if (forward_token == 0) {
return (0);
}
iovec.iov_base = orf_token;
iovec.iov_len = iov_len;
totemrrp_token_send (instance->totemrrp_handle,
&iovec,
1);
return (res);
}
static int token_hold_cancel_send (struct totemsrp_instance *instance)
{
struct token_hold_cancel token_hold_cancel;
struct iovec iovec[2];
/*
* Only cancel if the token is currently held
*/
if (instance->my_token_held == 0) {
return (0);
}
instance->my_token_held = 0;
/*
* Build message
*/
token_hold_cancel.header.type = MESSAGE_TYPE_TOKEN_HOLD_CANCEL;
token_hold_cancel.header.endian_detector = ENDIAN_LOCAL;
token_hold_cancel.header.nodeid = instance->my_id.addr[0].nodeid;
assert (token_hold_cancel.header.nodeid);
iovec[0].iov_base = &token_hold_cancel;
iovec[0].iov_len = sizeof (struct token_hold_cancel) -
sizeof (struct memb_ring_id);
iovec[1].iov_base = &instance->my_ring_id;
iovec[1].iov_len = sizeof (struct memb_ring_id);
totemrrp_mcast_flush_send (instance->totemrrp_handle, iovec, 2);
return (0);
}
//AAA
static int orf_token_send_initial (struct totemsrp_instance *instance)
{
struct orf_token orf_token;
int res;
orf_token.header.type = MESSAGE_TYPE_ORF_TOKEN;
orf_token.header.endian_detector = ENDIAN_LOCAL;
orf_token.header.encapsulated = 0;
orf_token.header.nodeid = instance->my_id.addr[0].nodeid;
assert (orf_token.header.nodeid);
orf_token.seq = SEQNO_START_MSG;
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;
orf_token.aru_addr = instance->my_id.addr[0].nodeid;
memcpy (&orf_token.ring_id, &instance->my_ring_id, sizeof (struct memb_ring_id));
orf_token.fcc = 0;
orf_token.backlog = 0;
orf_token.rtr_list_entries = 0;
res = token_send (instance, &orf_token, 1);
return (res);
}
static void memb_state_commit_token_update (
struct totemsrp_instance *instance,
struct memb_commit_token *commit_token)
{
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));
memb_list[commit_token->memb_index].aru = instance->old_ring_state_aru;
/*
* TODO high delivered is really instance->my_aru, but with safe this
* could change?
*/
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);
assert (commit_token->header.nodeid);
}
static void memb_state_commit_token_target_set (
struct totemsrp_instance *instance,
struct memb_commit_token *commit_token)
{
struct srp_addr *addr;
unsigned int i;
addr = (struct srp_addr *)commit_token->end_of_commit_token;
for (i = 0; i < instance->totem_config->interface_count; i++) {
totemrrp_token_target_set (
instance->totemrrp_handle,
&addr[commit_token->memb_index %
commit_token->addr_entries].addr[i],
i);
}
}
static int memb_state_commit_token_send (
struct totemsrp_instance *instance,
struct memb_commit_token *commit_token)
{
struct iovec iovec;
struct srp_addr *addr;
struct memb_commit_token_memb_entry *memb_list;
addr = (struct srp_addr *)commit_token->end_of_commit_token;
memb_list = (struct memb_commit_token_memb_entry *)(addr + commit_token->addr_entries);
commit_token->token_seq++;
iovec.iov_base = commit_token;
iovec.iov_len = sizeof (struct memb_commit_token) +
((sizeof (struct srp_addr) +
sizeof (struct memb_commit_token_memb_entry)) * commit_token->addr_entries);
/*
* Make a copy for retransmission if necessary
*/
memcpy (instance->orf_token_retransmit, commit_token, iovec.iov_len);
instance->orf_token_retransmit_size = iovec.iov_len;
totemrrp_token_send (instance->totemrrp_handle,
&iovec,
1);
/*
* Request retransmission of the commit token in case it is lost
*/
reset_token_retransmit_timeout (instance);
return (0);
}
static int memb_lowest_in_config (struct totemsrp_instance *instance)
{
struct srp_addr token_memb[PROCESSOR_COUNT_MAX];
int token_memb_entries = 0;
int i;
struct totem_ip_address *lowest_addr;
memb_set_subtract (token_memb, &token_memb_entries,
instance->my_proc_list, instance->my_proc_list_entries,
instance->my_failed_list, instance->my_failed_list_entries);
/*
* find representative by searching for smallest identifier
*/
-
+
lowest_addr = &token_memb[0].addr[0];
for (i = 1; i < token_memb_entries; i++) {
if (totemip_compare(lowest_addr, &token_memb[i].addr[0]) > 0) {
totemip_copy (lowest_addr, &token_memb[i].addr[0]);
}
}
return (totemip_compare (lowest_addr, &instance->my_id.addr[0]) == 0);
}
static int srp_addr_compare (const void *a, const void *b)
{
const struct srp_addr *srp_a = (const struct srp_addr *)a;
const struct srp_addr *srp_b = (const struct srp_addr *)b;
return (totemip_compare (&srp_a->addr[0], &srp_b->addr[0]));
}
static void memb_state_commit_token_create (
struct totemsrp_instance *instance,
struct memb_commit_token *commit_token)
{
struct srp_addr token_memb[PROCESSOR_COUNT_MAX];
struct srp_addr *addr;
struct memb_commit_token_memb_entry *memb_list;
int token_memb_entries = 0;
log_printf (instance->totemsrp_log_level_notice,
"Creating commit token because I am the rep.\n");
memb_set_subtract (token_memb, &token_memb_entries,
instance->my_proc_list, instance->my_proc_list_entries,
instance->my_failed_list, instance->my_failed_list_entries);
memset (commit_token, 0, sizeof (struct memb_commit_token));
commit_token->header.type = MESSAGE_TYPE_MEMB_COMMIT_TOKEN;
commit_token->header.endian_detector = ENDIAN_LOCAL;
commit_token->header.encapsulated = 0;
commit_token->header.nodeid = instance->my_id.addr[0].nodeid;
assert (commit_token->header.nodeid);
totemip_copy(&commit_token->ring_id.rep, &instance->my_id.addr[0]);
commit_token->ring_id.seq = instance->token_ring_id_seq + 4;
/*
* This qsort is necessary to ensure the commit token traverses
* the ring in the proper order
*/
qsort (token_memb, token_memb_entries, sizeof (struct srp_addr),
srp_addr_compare);
commit_token->memb_index = 0;
commit_token->addr_entries = token_memb_entries;
addr = (struct srp_addr *)commit_token->end_of_commit_token;
memb_list = (struct memb_commit_token_memb_entry *)(addr + commit_token->addr_entries);
memcpy (addr, token_memb,
token_memb_entries * sizeof (struct srp_addr));
memset (memb_list, 0,
sizeof (struct memb_commit_token_memb_entry) * token_memb_entries);
}
static void memb_join_message_send (struct totemsrp_instance *instance)
{
struct memb_join memb_join;
struct iovec iovec[3];
unsigned int iovs;
memb_join.header.type = MESSAGE_TYPE_MEMB_JOIN;
memb_join.header.endian_detector = ENDIAN_LOCAL;
memb_join.header.encapsulated = 0;
memb_join.header.nodeid = instance->my_id.addr[0].nodeid;
assert (memb_join.header.nodeid);
assert (srp_addr_equal (&instance->my_proc_list[0], &instance->my_proc_list[1]) == 0);
memb_join.ring_seq = instance->my_ring_id.seq;
memb_join.proc_list_entries = instance->my_proc_list_entries;
memb_join.failed_list_entries = instance->my_failed_list_entries;
srp_addr_copy (&memb_join.system_from, &instance->my_id);
-
+
iovec[0].iov_base = &memb_join;
iovec[0].iov_len = sizeof (struct memb_join);
iovec[1].iov_base = &instance->my_proc_list;
iovec[1].iov_len = instance->my_proc_list_entries *
sizeof (struct srp_addr);
if (instance->my_failed_list_entries == 0) {
iovs = 2;
} else {
iovs = 3;
iovec[2].iov_base = instance->my_failed_list;
iovec[2].iov_len = instance->my_failed_list_entries *
sizeof (struct srp_addr);
}
if (instance->totem_config->send_join_timeout) {
usleep (random() % (instance->totem_config->send_join_timeout * 1000));
}
totemrrp_mcast_flush_send (
instance->totemrrp_handle,
iovec,
iovs);
}
-static void memb_merge_detect_transmit (struct totemsrp_instance *instance)
+static void memb_merge_detect_transmit (struct totemsrp_instance *instance)
{
struct memb_merge_detect memb_merge_detect;
struct iovec iovec[2];
memb_merge_detect.header.type = MESSAGE_TYPE_MEMB_MERGE_DETECT;
memb_merge_detect.header.endian_detector = ENDIAN_LOCAL;
memb_merge_detect.header.encapsulated = 0;
memb_merge_detect.header.nodeid = instance->my_id.addr[0].nodeid;
srp_addr_copy (&memb_merge_detect.system_from, &instance->my_id);
assert (memb_merge_detect.header.nodeid);
iovec[0].iov_base = &memb_merge_detect;
iovec[0].iov_len = sizeof (struct memb_merge_detect) -
sizeof (struct memb_ring_id);
iovec[1].iov_base = &instance->my_ring_id;
iovec[1].iov_len = sizeof (struct memb_ring_id);
totemrrp_mcast_flush_send (instance->totemrrp_handle, iovec, 2);
}
static void memb_ring_id_create_or_load (
struct totemsrp_instance *instance,
struct memb_ring_id *memb_ring_id)
{
int fd;
int res;
char filename[256];
snprintf (filename, sizeof(filename), "%s/ringid_%s",
rundir, totemip_print (&instance->my_id.addr[0]));
fd = open (filename, O_RDONLY, 0700);
if (fd > 0) {
res = read (fd, &memb_ring_id->seq, sizeof (unsigned long long));
assert (res == sizeof (unsigned long long));
close (fd);
} else
if (fd == -1 && errno == ENOENT) {
memb_ring_id->seq = 0;
umask(0);
fd = open (filename, O_CREAT|O_RDWR, 0700);
if (fd == -1) {
log_printf (instance->totemsrp_log_level_warning,
"Couldn't create %s %s\n", filename, strerror (errno));
}
res = write (fd, &memb_ring_id->seq, sizeof (unsigned long long));
assert (res == sizeof (unsigned long long));
close (fd);
} else {
log_printf (instance->totemsrp_log_level_warning,
"Couldn't open %s %s\n", filename, strerror (errno));
}
-
+
totemip_copy(&memb_ring_id->rep, &instance->my_id.addr[0]);
assert (!totemip_zero_check(&memb_ring_id->rep));
instance->token_ring_id_seq = memb_ring_id->seq;
}
static void memb_ring_id_set_and_store (
struct totemsrp_instance *instance,
const 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));
snprintf (filename, sizeof(filename), "%s/ringid_%s",
rundir, totemip_print (&instance->my_id.addr[0]));
fd = open (filename, O_WRONLY, 0777);
if (fd == -1) {
fd = open (filename, O_CREAT|O_RDWR, 0777);
}
if (fd == -1) {
log_printf (instance->totemsrp_log_level_warning,
"Couldn't store new ring id %llx to stable storage (%s)\n",
instance->my_ring_id.seq, strerror (errno));
assert (0);
return;
}
log_printf (instance->totemsrp_log_level_notice,
"Storing new sequence id for ring %llx\n", instance->my_ring_id.seq);
//assert (fd > 0);
res = write (fd, &instance->my_ring_id.seq, sizeof (unsigned long long));
assert (res == sizeof (unsigned long long));
close (fd);
}
int totemsrp_callback_token_create (
hdb_handle_t handle,
void **handle_out,
enum totem_callback_token_type type,
int delete,
int (*callback_fn) (enum totem_callback_token_type type, const void *),
const void *data)
{
struct token_callback_instance *callback_handle;
struct totemsrp_instance *instance;
unsigned int res;
res = hdb_handle_get (&totemsrp_instance_database, handle,
(void *)&instance);
if (res != 0) {
goto error_exit;
}
token_hold_cancel_send (instance);
callback_handle = malloc (sizeof (struct token_callback_instance));
if (callback_handle == 0) {
return (-1);
}
*handle_out = (void *)callback_handle;
list_init (&callback_handle->list);
callback_handle->callback_fn = callback_fn;
callback_handle->data = (void *) data;
callback_handle->callback_type = type;
callback_handle->delete = delete;
switch (type) {
case TOTEM_CALLBACK_TOKEN_RECEIVED:
list_add (&callback_handle->list, &instance->token_callback_received_listhead);
break;
case TOTEM_CALLBACK_TOKEN_SENT:
list_add (&callback_handle->list, &instance->token_callback_sent_listhead);
break;
}
hdb_handle_put (&totemsrp_instance_database, handle);
error_exit:
return (0);
}
void totemsrp_callback_token_destroy (hdb_handle_t handle, void **handle_out)
{
struct token_callback_instance *h;
if (*handle_out) {
h = (struct token_callback_instance *)*handle_out;
list_del (&h->list);
free (h);
h = NULL;
*handle_out = 0;
}
}
static void token_callbacks_execute (
struct totemsrp_instance *instance,
enum totem_callback_token_type type)
{
struct list_head *list;
struct list_head *list_next;
struct list_head *callback_listhead = 0;
struct token_callback_instance *token_callback_instance;
int res;
int del;
switch (type) {
case TOTEM_CALLBACK_TOKEN_RECEIVED:
callback_listhead = &instance->token_callback_received_listhead;
break;
case TOTEM_CALLBACK_TOKEN_SENT:
callback_listhead = &instance->token_callback_sent_listhead;
break;
default:
assert (0);
}
-
+
for (list = callback_listhead->next; list != callback_listhead;
list = list_next) {
token_callback_instance = list_entry (list, struct token_callback_instance, list);
list_next = list->next;
del = token_callback_instance->delete;
if (del == 1) {
list_del (list);
}
res = token_callback_instance->callback_fn (
token_callback_instance->callback_type,
token_callback_instance->data);
/*
* This callback failed to execute, try it again on the next token
*/
if (res == -1 && del == 1) {
list_add (list, callback_listhead);
} else if (del) {
free (token_callback_instance);
}
}
}
/*
* Flow control functions
*/
static unsigned int backlog_get (struct totemsrp_instance *instance)
{
unsigned int backlog = 0;
if (instance->memb_state == MEMB_STATE_OPERATIONAL) {
backlog = queue_used (&instance->new_message_queue);
} else
if (instance->memb_state == MEMB_STATE_RECOVERY) {
backlog = queue_used (&instance->retrans_message_queue);
}
return (backlog);
}
static int fcc_calculate (
struct totemsrp_instance *instance,
struct orf_token *token)
{
unsigned int transmits_allowed;
unsigned int backlog_calc;
transmits_allowed = instance->totem_config->max_messages;
if (transmits_allowed > instance->totem_config->window_size - token->fcc) {
transmits_allowed = instance->totem_config->window_size - token->fcc;
}
instance->my_cbl = backlog_get (instance);
/*
* Only do backlog calculation if there is a backlog otherwise
* we would result in div by zero
*/
if (token->backlog + instance->my_cbl - instance->my_pbl) {
backlog_calc = (instance->totem_config->window_size * instance->my_pbl) /
(token->backlog + instance->my_cbl - instance->my_pbl);
if (backlog_calc > 0 && transmits_allowed > backlog_calc) {
transmits_allowed = backlog_calc;
}
}
return (transmits_allowed);
}
/*
* don't overflow the RTR sort queue
*/
static void fcc_rtr_limit (
struct totemsrp_instance *instance,
struct orf_token *token,
unsigned int *transmits_allowed)
{
assert ((QUEUE_RTR_ITEMS_SIZE_MAX - *transmits_allowed - instance->totem_config->window_size) >= 0);
if (sq_lt_compare (instance->last_released +
QUEUE_RTR_ITEMS_SIZE_MAX - *transmits_allowed -
instance->totem_config->window_size,
token->seq)) {
*transmits_allowed = 0;
}
}
static void fcc_token_update (
struct totemsrp_instance *instance,
struct orf_token *token,
unsigned int msgs_transmitted)
{
token->fcc += msgs_transmitted - instance->my_trc;
token->backlog += instance->my_cbl - instance->my_pbl;
assert (token->backlog >= 0);
instance->my_trc = msgs_transmitted;
instance->my_pbl = instance->my_cbl;
}
/*
* Message Handlers
*/
struct timeval tv_old;
/*
* message handler called when TOKEN message type received
*/
static int message_handler_orf_token (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed)
{
char token_storage[1500];
char token_convert[1500];
struct orf_token *token = NULL;
int forward_token;
unsigned int transmits_allowed;
unsigned int mcasted_retransmit;
unsigned int mcasted_regular;
unsigned int last_aru;
#ifdef GIVEINFO
struct timeval tv_current;
struct timeval tv_diff;
gettimeofday (&tv_current, NULL);
timersub (&tv_current, &tv_old, &tv_diff);
memcpy (&tv_old, &tv_current, sizeof (struct timeval));
log_printf (instance->totemsrp_log_level_notice,
"Time since last token %0.4f ms\n",
(((float)tv_diff.tv_sec) * 1000) + ((float)tv_diff.tv_usec)
/ 1000.0);
#endif
#ifdef TEST_DROP_ORF_TOKEN_PERCENTAGE
if (random()%100 < TEST_DROP_ORF_TOKEN_PERCENTAGE) {
return (0);
}
#endif
if (endian_conversion_needed) {
orf_token_endian_convert ((struct orf_token *)msg,
(struct orf_token *)token_convert);
msg = (struct orf_token *)token_convert;
}
/*
* Make copy of token and retransmit list in case we have
* to flush incoming messages from the kernel queue
*/
token = (struct orf_token *)token_storage;
memcpy (token, msg, sizeof (struct orf_token));
memcpy (&token->rtr_list[0], (char *)msg + sizeof (struct orf_token),
sizeof (struct rtr_item) * RETRANSMIT_ENTRIES_MAX);
/*
* Handle merge detection timeout
*/
if (token->seq == instance->my_last_seq) {
start_merge_detect_timeout (instance);
instance->my_seq_unchanged += 1;
} else {
cancel_merge_detect_timeout (instance);
cancel_token_hold_retransmit_timeout (instance);
instance->my_seq_unchanged = 0;
}
instance->my_last_seq = token->seq;
#ifdef TEST_RECOVERY_MSG_COUNT
if (instance->memb_state == MEMB_STATE_OPERATIONAL && token->seq > TEST_RECOVERY_MSG_COUNT) {
return (0);
}
#endif
totemrrp_recv_flush (instance->totemrrp_handle);
/*
* Determine if we should hold (in reality drop) the token
*/
instance->my_token_held = 0;
if (totemip_equal(&instance->my_ring_id.rep, &instance->my_id.addr[0]) &&
instance->my_seq_unchanged > instance->totem_config->seqno_unchanged_const) {
instance->my_token_held = 1;
} else
if (!totemip_equal(&instance->my_ring_id.rep, &instance->my_id.addr[0]) &&
instance->my_seq_unchanged >= instance->totem_config->seqno_unchanged_const) {
instance->my_token_held = 1;
}
/*
* Hold onto token when there is no activity on ring and
* this processor is the ring rep
*/
forward_token = 1;
if (totemip_equal(&instance->my_ring_id.rep, &instance->my_id.addr[0])) {
if (instance->my_token_held) {
- forward_token = 0;
+ forward_token = 0;
}
}
token_callbacks_execute (instance, TOTEM_CALLBACK_TOKEN_RECEIVED);
switch (instance->memb_state) {
case MEMB_STATE_COMMIT:
/* Discard token */
break;
case MEMB_STATE_OPERATIONAL:
messages_free (instance, token->aru);
case MEMB_STATE_GATHER:
/*
* DO NOT add break, we use different free mechanism in recovery state
*/
case MEMB_STATE_RECOVERY:
last_aru = instance->my_last_aru;
instance->my_last_aru = token->aru;
/*
* Discard tokens from another configuration
*/
if (memcmp (&token->ring_id, &instance->my_ring_id,
sizeof (struct memb_ring_id)) != 0) {
if ((forward_token)
&& instance->use_heartbeat) {
reset_heartbeat_timeout(instance);
- }
+ }
else {
cancel_heartbeat_timeout(instance);
}
return (0); /* discard token */
}
/*
* Discard retransmitted tokens
*/
if (sq_lte_compare (token->token_seq, instance->my_token_seq)) {
/*
* If this processor receives a retransmitted token, it is sure
* the previous processor is still alive. As a result, it can
* reset its token timeout. If some processor previous to that
* has failed, it will eventually not execute a reset of the
* token timeout, and will cause a reconfiguration to occur.
*/
reset_token_timeout (instance);
if ((forward_token)
&& instance->use_heartbeat) {
reset_heartbeat_timeout(instance);
}
else {
cancel_heartbeat_timeout(instance);
}
return (0); /* discard token */
- }
+ }
transmits_allowed = fcc_calculate (instance, token);
mcasted_retransmit = orf_token_rtr (instance, token, &transmits_allowed);
fcc_rtr_limit (instance, token, &transmits_allowed);
mcasted_regular = orf_token_mcast (instance, token, transmits_allowed);
fcc_token_update (instance, token, mcasted_retransmit +
mcasted_regular);
-
+
if (sq_lt_compare (instance->my_aru, token->aru) ||
instance->my_id.addr[0].nodeid == token->aru_addr ||
token->aru_addr == 0) {
-
+
token->aru = instance->my_aru;
if (token->aru == token->seq) {
token->aru_addr = 0;
} else {
token->aru_addr = instance->my_id.addr[0].nodeid;
}
}
if (token->aru == last_aru && token->aru_addr != 0) {
instance->my_aru_count += 1;
} else {
instance->my_aru_count = 0;
}
if (instance->my_aru_count > instance->totem_config->fail_to_recv_const &&
token->aru_addr != instance->my_id.addr[0].nodeid) {
-
+
log_printf (instance->totemsrp_log_level_error,
"FAILED TO RECEIVE\n");
// TODO if we fail to receive, it may be possible to end with a gather
// state of proc == failed = 0 entries
/* THIS IS A BIG TODO
memb_set_merge (&token->aru_addr, 1,
instance->my_failed_list,
&instance->my_failed_list_entries);
*/
ring_state_restore (instance);
memb_state_gather_enter (instance, 6);
} else {
instance->my_token_seq = token->token_seq;
token->token_seq += 1;
if (instance->memb_state == MEMB_STATE_RECOVERY) {
/*
* instance->my_aru == instance->my_high_seq_received means this processor
* has recovered all messages it can recover
* (ie: its retrans queue is empty)
*/
if (queue_is_empty (&instance->retrans_message_queue) == 0) {
if (token->retrans_flg == 0) {
token->retrans_flg = 1;
instance->my_set_retrans_flg = 1;
}
} else
if (token->retrans_flg == 1 && instance->my_set_retrans_flg) {
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, 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, token->aru);
- if (token->retrans_flg == 0) {
+ if (token->retrans_flg == 0) {
instance->my_retrans_flg_count += 1;
} else {
instance->my_retrans_flg_count = 0;
}
if (instance->my_retrans_flg_count == 2) {
instance->my_install_seq = token->seq;
}
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_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 &&
sq_lte_compare (instance->my_install_seq, token->aru)) {
instance->my_rotation_counter += 1;
} else {
instance->my_rotation_counter = 0;
}
if (instance->my_rotation_counter == 2) {
log_printf (instance->totemsrp_log_level_debug,
"retrans flag count %x token aru %x install seq %x aru %x %x\n",
instance->my_retrans_flg_count, token->aru, instance->my_install_seq,
instance->my_aru, token->seq);
memb_state_operational_enter (instance);
instance->my_rotation_counter = 0;
instance->my_retrans_flg_count = 0;
}
}
-
+
totemrrp_send_flush (instance->totemrrp_handle);
- token_send (instance, token, forward_token);
+ token_send (instance, token, forward_token);
#ifdef GIVEINFO
gettimeofday (&tv_current, NULL);
timersub (&tv_current, &tv_old, &tv_diff);
memcpy (&tv_old, &tv_current, sizeof (struct timeval));
log_printf (instance->totemsrp_log_level_notice,
"I held %0.4f ms\n",
((float)tv_diff.tv_usec) / 1000.0);
#endif
if (instance->memb_state == MEMB_STATE_OPERATIONAL) {
messages_deliver_to_app (instance, 0,
instance->my_high_seq_received);
}
/*
* Deliver messages after token has been transmitted
* to improve performance
*/
reset_token_timeout (instance); // REVIEWED
reset_token_retransmit_timeout (instance); // REVIEWED
if (totemip_equal(&instance->my_id.addr[0], &instance->my_ring_id.rep) &&
instance->my_token_held == 1) {
start_token_hold_retransmit_timeout (instance);
}
token_callbacks_execute (instance, TOTEM_CALLBACK_TOKEN_SENT);
}
break;
}
if ((forward_token)
&& instance->use_heartbeat) {
reset_heartbeat_timeout(instance);
}
else {
cancel_heartbeat_timeout(instance);
}
return (0);
}
static void messages_deliver_to_app (
struct totemsrp_instance *instance,
int skip,
unsigned int end_point)
{
struct sort_queue_item *sort_queue_item_p;
unsigned int i;
int res;
struct mcast *mcast_in;
struct mcast mcast_header;
unsigned int range = 0;
int endian_conversion_required;
unsigned int my_high_delivered_stored = 0;
range = end_point - instance->my_high_delivered;
if (range) {
log_printf (instance->totemsrp_log_level_debug,
"Delivering %x to %x\n", instance->my_high_delivered,
end_point);
}
assert (range < 10240);
my_high_delivered_stored = instance->my_high_delivered;
/*
* Deliver messages in order from rtr queue to pending delivery queue
*/
for (i = 1; i <= range; i++) {
void *ptr = 0;
/*
* If out of range of sort queue, stop assembly
*/
res = sq_in_range (&instance->regular_sort_queue,
my_high_delivered_stored + i);
if (res == 0) {
break;
}
res = sq_item_get (&instance->regular_sort_queue,
my_high_delivered_stored + i, &ptr);
/*
* If hole, stop assembly
*/
if (res != 0 && skip == 0) {
break;
}
instance->my_high_delivered = my_high_delivered_stored + i;
if (res != 0) {
continue;
}
sort_queue_item_p = ptr;
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_header.system_from,
1,
instance->my_deliver_memb_list,
instance->my_deliver_memb_entries) == 0) {
instance->my_high_delivered = my_high_delivered_stored + i;
continue;
}
/*
* Message found
*/
log_printf (instance->totemsrp_log_level_debug,
"Delivering MCAST message with seq %x to pending delivery queue\n",
mcast_header.seq);
/*
* Message is locally originated multicast
*/
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.header.nodeid,
&sort_queue_item_p->iovec[1],
sort_queue_item_p->iov_len - 1,
endian_conversion_required);
} else {
sort_queue_item_p->iovec[0].iov_len -= sizeof (struct mcast);
sort_queue_item_p->iovec[0].iov_base = (char *)sort_queue_item_p->iovec[0].iov_base + sizeof (struct mcast);
instance->totemsrp_deliver_fn (
mcast_header.header.nodeid,
sort_queue_item_p->iovec,
sort_queue_item_p->iov_len,
endian_conversion_required);
sort_queue_item_p->iovec[0].iov_len += sizeof (struct mcast);
sort_queue_item_p->iovec[0].iov_base = (char *)sort_queue_item_p->iovec[0].iov_base - sizeof (struct mcast);
}
//TODO instance->stats_delv += 1;
}
}
/*
* recv message handler called when MCAST message type received
*/
static int message_handler_mcast (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed)
{
struct sort_queue_item sort_queue_item;
struct sq *sort_queue;
struct mcast mcast_header;
-
+
if (endian_conversion_needed) {
mcast_endian_convert (msg, &mcast_header);
} else {
memcpy (&mcast_header, msg, sizeof (struct mcast));
}
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
if (random()%100 < TEST_DROP_MCAST_PERCENTAGE) {
printf ("dropping message %d\n", mcast_header.seq);
return (0);
} else {
printf ("accepting message %d\n", mcast_header.seq);
}
#endif
if (srp_addr_equal (&mcast_header.system_from, &instance->my_id) == 0) {
cancel_token_retransmit_timeout (instance);
}
/*
* If the message is foreign execute the switch below
*/
if (memcmp (&instance->my_ring_id, &mcast_header.ring_id,
sizeof (struct memb_ring_id)) != 0) {
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
memb_set_merge (
&mcast_header.system_from, 1,
instance->my_proc_list, &instance->my_proc_list_entries);
memb_state_gather_enter (instance, 7);
break;
case MEMB_STATE_GATHER:
if (!memb_set_subset (
&mcast_header.system_from,
1,
instance->my_proc_list,
instance->my_proc_list_entries)) {
memb_set_merge (&mcast_header.system_from, 1,
instance->my_proc_list, &instance->my_proc_list_entries);
memb_state_gather_enter (instance, 8);
return (0);
}
break;
case MEMB_STATE_COMMIT:
/* discard message */
break;
case MEMB_STATE_RECOVERY:
/* discard message */
break;
}
return (0);
}
log_printf (instance->totemsrp_log_level_debug,
"Received ringid(%s:%lld) seq %x\n",
totemip_print (&mcast_header.ring_id.rep),
mcast_header.ring_id.seq,
mcast_header.seq);
/*
* Add mcast message to rtr queue if not already in rtr queue
* otherwise free io vectors
*/
if (msg_len > 0 && msg_len < FRAME_SIZE_MAX &&
- sq_in_range (sort_queue, mcast_header.seq) &&
+ sq_in_range (sort_queue, mcast_header.seq) &&
sq_item_inuse (sort_queue, mcast_header.seq) == 0) {
/*
* Allocate new multicast memory block
*/
// TODO LEAK
sort_queue_item.iovec[0].iov_base = malloc (msg_len);
if (sort_queue_item.iovec[0].iov_base == 0) {
return (-1); /* error here is corrected by the algorithm */
}
memcpy (sort_queue_item.iovec[0].iov_base, msg, msg_len);
sort_queue_item.iovec[0].iov_len = msg_len;
assert (sort_queue_item.iovec[0].iov_len > 0);
assert (sort_queue_item.iovec[0].iov_len < FRAME_SIZE_MAX);
sort_queue_item.iov_len = 1;
-
+
if (sq_lt_compare (instance->my_high_seq_received,
mcast_header.seq)) {
instance->my_high_seq_received = mcast_header.seq;
}
sq_item_add (sort_queue, &sort_queue_item, mcast_header.seq);
}
update_aru (instance);
if (instance->memb_state == MEMB_STATE_OPERATIONAL) {
messages_deliver_to_app (instance, 0, instance->my_high_seq_received);
}
/* TODO remove from retrans message queue for old ring in recovery state */
return (0);
}
static int message_handler_memb_merge_detect (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed)
{
struct memb_merge_detect memb_merge_detect;
if (endian_conversion_needed) {
memb_merge_detect_endian_convert (msg, &memb_merge_detect);
} else {
memcpy (&memb_merge_detect, msg,
sizeof (struct memb_merge_detect));
}
/*
* do nothing if this is a merge detect from this configuration
*/
if (memcmp (&instance->my_ring_id, &memb_merge_detect.ring_id,
sizeof (struct memb_ring_id)) == 0) {
return (0);
}
/*
* Execute merge operation
*/
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
memb_set_merge (&memb_merge_detect.system_from, 1,
instance->my_proc_list, &instance->my_proc_list_entries);
memb_state_gather_enter (instance, 9);
break;
case MEMB_STATE_GATHER:
if (!memb_set_subset (
&memb_merge_detect.system_from,
1,
instance->my_proc_list,
instance->my_proc_list_entries)) {
memb_set_merge (&memb_merge_detect.system_from, 1,
instance->my_proc_list, &instance->my_proc_list_entries);
memb_state_gather_enter (instance, 10);
return (0);
}
break;
case MEMB_STATE_COMMIT:
/* do nothing in commit */
break;
case MEMB_STATE_RECOVERY:
/* do nothing in recovery */
break;
}
return (0);
}
static int memb_join_process (
struct totemsrp_instance *instance,
const struct memb_join *memb_join)
{
unsigned char *commit_token_storage[TOKEN_SIZE_MAX];
struct memb_commit_token *my_commit_token =
(struct memb_commit_token *)commit_token_storage;
struct srp_addr *proc_list;
struct srp_addr *failed_list;
proc_list = (struct srp_addr *)memb_join->end_of_memb_join;
failed_list = proc_list + memb_join->proc_list_entries;
if (memb_set_equal (proc_list,
memb_join->proc_list_entries,
instance->my_proc_list,
instance->my_proc_list_entries) &&
memb_set_equal (failed_list,
memb_join->failed_list_entries,
instance->my_failed_list,
instance->my_failed_list_entries)) {
memb_consensus_set (instance, &memb_join->system_from);
-
+
if (memb_consensus_agreed (instance) &&
memb_lowest_in_config (instance)) {
memb_state_commit_token_create (instance, my_commit_token);
-
+
memb_state_commit_enter (instance, my_commit_token);
} else {
return (0);
}
} else
if (memb_set_subset (proc_list,
memb_join->proc_list_entries,
instance->my_proc_list,
instance->my_proc_list_entries) &&
memb_set_subset (failed_list,
memb_join->failed_list_entries,
instance->my_failed_list,
instance->my_failed_list_entries)) {
return (0);
} else
if (memb_set_subset (&memb_join->system_from, 1,
instance->my_failed_list, instance->my_failed_list_entries)) {
return (0);
} else {
memb_set_merge (proc_list,
memb_join->proc_list_entries,
instance->my_proc_list, &instance->my_proc_list_entries);
if (memb_set_subset (
&instance->my_id, 1,
failed_list, memb_join->failed_list_entries)) {
memb_set_merge (
&memb_join->system_from, 1,
instance->my_failed_list, &instance->my_failed_list_entries);
} else {
memb_set_merge (failed_list,
memb_join->failed_list_entries,
instance->my_failed_list, &instance->my_failed_list_entries);
}
memb_state_gather_enter (instance, 11);
return (1); /* gather entered */
}
return (0); /* gather not entered */
}
static void memb_join_endian_convert (const struct memb_join *in, struct memb_join *out)
{
int i;
struct srp_addr *in_proc_list;
struct srp_addr *in_failed_list;
struct srp_addr *out_proc_list;
struct srp_addr *out_failed_list;
out->header.type = in->header.type;
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
srp_addr_copy_endian_convert (&out->system_from, &in->system_from);
out->proc_list_entries = swab32 (in->proc_list_entries);
out->failed_list_entries = swab32 (in->failed_list_entries);
out->ring_seq = swab64 (in->ring_seq);
in_proc_list = (struct srp_addr *)in->end_of_memb_join;
in_failed_list = in_proc_list + out->proc_list_entries;
out_proc_list = (struct srp_addr *)out->end_of_memb_join;
out_failed_list = out_proc_list + out->proc_list_entries;
for (i = 0; i < out->proc_list_entries; i++) {
srp_addr_copy_endian_convert (&out_proc_list[i], &in_proc_list[i]);
}
for (i = 0; i < out->failed_list_entries; i++) {
srp_addr_copy_endian_convert (&out_failed_list[i], &in_failed_list[i]);
}
}
static void memb_commit_token_endian_convert (const struct memb_commit_token *in, struct memb_commit_token *out)
{
int i;
struct srp_addr *in_addr = (struct srp_addr *)in->end_of_commit_token;
struct srp_addr *out_addr = (struct srp_addr *)out->end_of_commit_token;
struct memb_commit_token_memb_entry *in_memb_list;
struct memb_commit_token_memb_entry *out_memb_list;
out->header.type = in->header.type;
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
out->token_seq = swab32 (in->token_seq);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
out->ring_id.seq = swab64 (in->ring_id.seq);
out->retrans_flg = swab32 (in->retrans_flg);
out->memb_index = swab32 (in->memb_index);
out->addr_entries = swab32 (in->addr_entries);
in_memb_list = (struct memb_commit_token_memb_entry *)(in_addr + out->addr_entries);
out_memb_list = (struct memb_commit_token_memb_entry *)(out_addr + out->addr_entries);
for (i = 0; i < out->addr_entries; i++) {
srp_addr_copy_endian_convert (&out_addr[i], &in_addr[i]);
/*
* Only convert the memb entry if it has been set
*/
if (in_memb_list[i].ring_id.rep.family != 0) {
totemip_copy_endian_convert (&out_memb_list[i].ring_id.rep,
&in_memb_list[i].ring_id.rep);
out_memb_list[i].ring_id.seq =
swab64 (in_memb_list[i].ring_id.seq);
out_memb_list[i].aru = swab32 (in_memb_list[i].aru);
out_memb_list[i].high_delivered = swab32 (in_memb_list[i].high_delivered);
out_memb_list[i].received_flg = swab32 (in_memb_list[i].received_flg);
}
}
}
static void orf_token_endian_convert (const struct orf_token *in, struct orf_token *out)
{
int i;
out->header.type = in->header.type;
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
out->seq = swab32 (in->seq);
out->token_seq = swab32 (in->token_seq);
out->aru = swab32 (in->aru);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
out->aru_addr = swab32(in->aru_addr);
out->ring_id.seq = swab64 (in->ring_id.seq);
out->fcc = swab32 (in->fcc);
out->backlog = swab32 (in->backlog);
out->retrans_flg = swab32 (in->retrans_flg);
out->rtr_list_entries = swab32 (in->rtr_list_entries);
for (i = 0; i < out->rtr_list_entries; i++) {
totemip_copy_endian_convert(&out->rtr_list[i].ring_id.rep, &in->rtr_list[i].ring_id.rep);
out->rtr_list[i].ring_id.seq = swab64 (in->rtr_list[i].ring_id.seq);
out->rtr_list[i].seq = swab32 (in->rtr_list[i].seq);
}
}
static void mcast_endian_convert (const struct mcast *in, struct mcast *out)
{
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);
out->ring_id.seq = swab64 (in->ring_id.seq);
out->node_id = swab32 (in->node_id);
out->guarantee = swab32 (in->guarantee);
srp_addr_copy_endian_convert (&out->system_from, &in->system_from);
}
static void memb_merge_detect_endian_convert (
const struct memb_merge_detect *in,
struct memb_merge_detect *out)
{
out->header.type = in->header.type;
out->header.endian_detector = ENDIAN_LOCAL;
out->header.nodeid = swab32 (in->header.nodeid);
totemip_copy_endian_convert(&out->ring_id.rep, &in->ring_id.rep);
out->ring_id.seq = swab64 (in->ring_id.seq);
srp_addr_copy_endian_convert (&out->system_from, &in->system_from);
}
static int message_handler_memb_join (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed)
{
const struct memb_join *memb_join;
struct memb_join *memb_join_convert = alloca (msg_len);
int gather_entered;
if (endian_conversion_needed) {
memb_join = memb_join_convert;
memb_join_endian_convert (msg, memb_join_convert);
} else {
memb_join = msg;
}
if (instance->token_ring_id_seq < memb_join->ring_seq) {
instance->token_ring_id_seq = memb_join->ring_seq;
}
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
gather_entered = memb_join_process (instance,
memb_join);
if (gather_entered == 0) {
memb_state_gather_enter (instance, 12);
}
break;
case MEMB_STATE_GATHER:
memb_join_process (instance, memb_join);
break;
-
+
case MEMB_STATE_COMMIT:
if (memb_set_subset (&memb_join->system_from,
1,
instance->my_new_memb_list,
instance->my_new_memb_entries) &&
memb_join->ring_seq >= instance->my_ring_id.seq) {
memb_join_process (instance, memb_join);
memb_state_gather_enter (instance, 13);
}
break;
case MEMB_STATE_RECOVERY:
if (memb_set_subset (&memb_join->system_from,
1,
instance->my_new_memb_list,
instance->my_new_memb_entries) &&
memb_join->ring_seq >= instance->my_ring_id.seq) {
ring_state_restore (instance);
memb_join_process (instance, memb_join);
memb_state_gather_enter (instance, 14);
}
break;
}
return (0);
}
static int message_handler_memb_commit_token (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed)
{
struct memb_commit_token *memb_commit_token_convert = alloca (msg_len);
struct memb_commit_token *memb_commit_token;
struct srp_addr sub[PROCESSOR_COUNT_MAX];
int sub_entries;
struct srp_addr *addr;
struct memb_commit_token_memb_entry *memb_list;
log_printf (instance->totemsrp_log_level_debug,
"got commit token\n");
if (endian_conversion_needed) {
memb_commit_token_endian_convert (msg, memb_commit_token_convert);
} else {
memcpy (memb_commit_token_convert, msg, msg_len);
}
memb_commit_token = memb_commit_token_convert;
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);
#ifdef TEST_DROP_COMMIT_TOKEN_PERCENTAGE
if (random()%100 < TEST_DROP_COMMIT_TOKEN_PERCENTAGE) {
return (0);
}
#endif
switch (instance->memb_state) {
case MEMB_STATE_OPERATIONAL:
/* discard token */
break;
case MEMB_STATE_GATHER:
memb_set_subtract (sub, &sub_entries,
instance->my_proc_list, instance->my_proc_list_entries,
instance->my_failed_list, instance->my_failed_list_entries);
-
+
if (memb_set_equal (addr,
memb_commit_token->addr_entries,
sub,
sub_entries) &&
memb_commit_token->ring_id.seq > instance->my_ring_id.seq) {
memb_state_commit_enter (instance, memb_commit_token);
}
break;
case MEMB_STATE_COMMIT:
/*
* 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;
case MEMB_STATE_RECOVERY:
if (totemip_equal (&instance->my_id.addr[0], &instance->my_ring_id.rep)) {
log_printf (instance->totemsrp_log_level_notice,
"Sending initial ORF token\n");
// TODO convert instead of initiate
orf_token_send_initial (instance);
reset_token_timeout (instance); // REVIEWED
reset_token_retransmit_timeout (instance); // REVIEWED
}
break;
}
return (0);
}
static int message_handler_token_hold_cancel (
struct totemsrp_instance *instance,
const void *msg,
size_t msg_len,
int endian_conversion_needed)
{
const struct token_hold_cancel *token_hold_cancel = msg;
if (memcmp (&token_hold_cancel->ring_id, &instance->my_ring_id,
sizeof (struct memb_ring_id)) == 0) {
instance->my_seq_unchanged = 0;
if (totemip_equal(&instance->my_ring_id.rep, &instance->my_id.addr[0])) {
timer_function_token_retransmit_timeout (instance);
}
}
return (0);
}
void main_deliver_fn (
void *context,
const void *msg,
size_t msg_len)
{
struct totemsrp_instance *instance = context;
const struct message_header *message_header = msg;
if (msg_len < sizeof (struct message_header)) {
log_printf (instance->totemsrp_log_level_security,
"Received message is too short... ignoring %u.\n",
(unsigned int)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
*/
totemsrp_message_handlers.handler_functions[(int)message_header->type] (
instance,
msg,
msg_len,
message_header->endian_detector != ENDIAN_LOCAL);
}
void main_iface_change_fn (
void *context,
const struct totem_ip_address *iface_addr,
unsigned int iface_no)
{
struct totemsrp_instance *instance = context;
totemip_copy (&instance->my_id.addr[iface_no], iface_addr);
assert (instance->my_id.addr[iface_no].nodeid);
totemip_copy (&instance->my_memb_list[0].addr[iface_no], iface_addr);
if (instance->iface_changes++ == 0) {
memb_ring_id_create_or_load (instance, &instance->my_ring_id);
log_printf (
instance->totemsrp_log_level_notice,
"Created or loaded sequence id %lld.%s for this ring.\n",
instance->my_ring_id.seq,
totemip_print (&instance->my_ring_id.rep));
}
if (instance->iface_changes >= instance->totem_config->interface_count) {
memb_state_gather_enter (instance, 15);
}
}
void totemsrp_net_mtu_adjust (struct totem_config *totem_config) {
totem_config->net_mtu -= sizeof (struct mcast);
}
diff --git a/exec/util.c b/exec/util.c
index 82f80704..2e669bba 100644
--- a/exec/util.c
+++ b/exec/util.c
@@ -1,140 +1,140 @@
/*
* Copyright (c) 2002-2004 MontaVista Software, Inc.
* Copyright (c) 2004 Open Source Development Lab
* Copyright (c) 2006-2007, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com), Mark Haverkamp (markh@osdl.org)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <corosync/corotypes.h>
#include <corosync/list.h>
#include <corosync/engine/logsys.h>
#include "util.h"
LOGSYS_DECLARE_SUBSYS ("MAIN");
/*
* Compare two names. returns non-zero on match.
*/
-int name_match(cs_name_t *name1, cs_name_t *name2)
+int name_match(cs_name_t *name1, cs_name_t *name2)
{
if (name1->length == name2->length) {
return ((strncmp ((char *)name1->value, (char *)name2->value,
name1->length)) == 0);
- }
+ }
return 0;
}
/*
* Get the time of day and convert to nanoseconds
*/
cs_time_t clust_time_now(void)
{
struct timeval tv;
cs_time_t time_now;
if (gettimeofday(&tv, 0)) {
return 0ULL;
}
time_now = (cs_time_t)(tv.tv_sec) * 1000000000ULL;
time_now += (cs_time_t)(tv.tv_usec) * 1000ULL;
return time_now;
}
void _corosync_out_of_memory_error (void)
{
assert (0==1);
exit (EXIT_FAILURE);
}
void _corosync_exit_error (
enum e_ais_done err, const char *file, unsigned int line)
{
log_printf (LOGSYS_LEVEL_ERROR, "AIS Executive exiting "
"with status %d at %s:%u.\n", err, file, line);
logsys_fork_completed ();
logsys_flush ();
exit (err);
}
#define min(a,b) ((a) < (b) ? (a) : (b))
char *getcs_name_t (cs_name_t *name)
{
static char ret_name[CS_MAX_NAME_LENGTH];
/* if string is corrupt (non-terminated), ensure it's displayed safely */
if (name->length >= CS_MAX_NAME_LENGTH || name->value[name->length] != '\0') {
memset (ret_name, 0, sizeof (ret_name));
memcpy (ret_name, name->value, min(name->length, CS_MAX_NAME_LENGTH -1));
return (ret_name);
}
return ((char *)name->value);
}
char *strchr_rs (const char *haystack, int byte)
{
const char *end_address = strchr (haystack, byte);
if (end_address) {
end_address += 1; /* skip past { or = */
end_address += strspn (end_address, " \t");
}
return ((char *) end_address);
}
void setcs_name_t (cs_name_t *name, char *str) {
strncpy ((char *)name->value, str, CS_MAX_NAME_LENGTH);
if (strlen ((char *)name->value) > CS_MAX_NAME_LENGTH) {
name->length = CS_MAX_NAME_LENGTH;
} else {
name->length = strlen (str);
}
}
int cs_name_tisEqual (cs_name_t *str1, char *str2) {
if (str1->length == strlen (str2)) {
return ((strncmp ((char *)str1->value, (char *)str2,
str1->length)) == 0);
} else {
return 0;
}
}
diff --git a/exec/vsf.h b/exec/vsf.h
index 61583ba3..1bd6f4cf 100644
--- a/exec/vsf.h
+++ b/exec/vsf.h
@@ -1,57 +1,57 @@
/*
* Copyright (c) 2006 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.
*/
#ifndef VSF_H_DEFINED
#define VSF_H_DEFINED
struct corosync_api_v1;
struct corosync_vsf_iface_ver0 {
/*
* Executes a callback whenever component changes
*/
int (*init) (
struct corosync_api_v1 *api,
void (*primary_callback_fn) (
unsigned int *view_list,
int view_list_entries,
int primary_designated,
struct memb_ring_id *ring_id));
/*
* Returns 1 if we are primary component, 0 if not
*/
int (*primary) (void);
};
#endif /* VSF_H_DEFINED */
diff --git a/exec/vsf_ykd.c b/exec/vsf_ykd.c
index e3020493..bc128530 100644
--- a/exec/vsf_ykd.c
+++ b/exec/vsf_ykd.c
@@ -1,549 +1,549 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <corosync/engine/logsys.h>
#include <corosync/ipc_gen.h>
#include <corosync/engine/coroapi.h>
#include <corosync/engine/quorum.h>
#include <corosync/swab.h>
#include <corosync/lcr/lcr_comp.h>
LOGSYS_DECLARE_SUBSYS ("YKD");
#define YKD_PROCESSOR_COUNT_MAX 32
enum ykd_header_values {
YKD_HEADER_SENDSTATE = 0,
YKD_HEADER_ATTEMPT = 1
};
enum ykd_mode {
YKD_MODE_SENDSTATE = 0,
YKD_MODE_ATTEMPT = 1
};
struct ykd_header {
int id;
};
struct ykd_session {
unsigned int member_list[YKD_PROCESSOR_COUNT_MAX];
int member_list_entries;
int session_id;
};
struct ykd_state {
struct ykd_session last_primary;
struct ykd_session last_formed[YKD_PROCESSOR_COUNT_MAX];
int last_formed_entries;
struct ykd_session ambiguous_sessions[YKD_PROCESSOR_COUNT_MAX];
int ambiguous_sessions_entries;
int session_id;
};
struct state_received {
unsigned int nodeid;
int received;
struct ykd_state ykd_state;
};
struct ykd_state ykd_state;
static hdb_handle_t ykd_group_handle;
static struct state_received state_received_confchg[YKD_PROCESSOR_COUNT_MAX];
static int state_received_confchg_entries;
static struct state_received state_received_process[YKD_PROCESSOR_COUNT_MAX];
static int state_received_process_entries;
static enum ykd_mode ykd_mode;
static unsigned int view_list[YKD_PROCESSOR_COUNT_MAX];
static int view_list_entries;
static int session_id_max;
static struct ykd_session *last_primary_max;
static struct ykd_session ambiguous_sessions_max[YKD_PROCESSOR_COUNT_MAX];
static int ambiguous_sessions_max_entries;
static int primary_designated = 0;
static struct memb_ring_id ykd_ring_id;
hdb_handle_t schedwrk_attempt_send_callback_handle;
hdb_handle_t schedwrk_state_send_callback_handle;
static struct corosync_api_v1 *api;
static void (*ykd_primary_callback_fn) (
const unsigned int *view_list,
size_t view_list_entries,
int primary_designated,
struct memb_ring_id *ring_id) = NULL;
static void ykd_state_init (void)
{
ykd_state.session_id = 0;
ykd_state.last_formed_entries = 0;
ykd_state.ambiguous_sessions_entries = 0;
ykd_state.last_primary.session_id = 0;
ykd_state.last_primary.member_list_entries = 0;
}
static int ykd_state_send_msg (const void *context)
{
struct iovec iovec[2];
struct ykd_header header;
int res;
header.id = YKD_HEADER_SENDSTATE;
-
+
iovec[0].iov_base = (char *)&header;
iovec[0].iov_len = sizeof (struct ykd_header);
iovec[1].iov_base = (char *)&ykd_state;
iovec[1].iov_len = sizeof (struct ykd_state);
res = api->tpg_joined_mcast (ykd_group_handle, iovec, 2,
TOTEM_AGREED);
return (res);
}
static void ykd_state_send (void)
{
api->schedwrk_create (
&schedwrk_state_send_callback_handle,
ykd_state_send_msg,
NULL);
}
static int ykd_attempt_send_msg (const void *context)
{
struct iovec iovec;
struct ykd_header header;
int res;
header.id = YKD_HEADER_SENDSTATE;
-
+
iovec.iov_base = (char *)&header;
iovec.iov_len = sizeof (struct ykd_header);
res = api->tpg_joined_mcast (ykd_group_handle, &iovec, 1,
TOTEM_AGREED);
return (res);
}
static void ykd_attempt_send (void)
{
api->schedwrk_create (
&schedwrk_attempt_send_callback_handle,
ykd_attempt_send_msg,
NULL);
}
static void compute (void)
{
int i;
int j;
session_id_max = 0;
last_primary_max = &state_received_process[0].ykd_state.last_primary;
ambiguous_sessions_max_entries = 0;
for (i = 0; i < state_received_process_entries; i++) {
/*
* Calculate maximum session id
*/
if (state_received_process[i].ykd_state.session_id > session_id_max) {
session_id_max = state_received_process[i].ykd_state.session_id;
}
/*
* Calculate maximum primary id
*/
if (state_received_process[i].ykd_state.last_primary.session_id > last_primary_max->session_id) {
last_primary_max = &state_received_process[i].ykd_state.last_primary;
}
/*
* generate the maximum ambiguous sessions list
*/
for (j = 0; j < state_received_process[i].ykd_state.ambiguous_sessions_entries; j++) {
if (state_received_process[i].ykd_state.ambiguous_sessions[j].session_id > last_primary_max->session_id) {
memcpy (&ambiguous_sessions_max[ambiguous_sessions_max_entries],
&state_received_process[i].ykd_state.ambiguous_sessions[j],
sizeof (struct ykd_session));
ambiguous_sessions_max_entries += 1;
}
}
}
}
static int subquorum (
unsigned int *member_list,
int member_list_entries,
struct ykd_session *session)
{
int intersections = 0;
int i;
int j;
for (i = 0; i < member_list_entries; i++) {
for (j = 0; j < session->member_list_entries; j++) {
if (member_list[i] == session->member_list[j]) {
intersections += 1;
}
}
}
/*
* even split
*/
if (intersections == (session->member_list_entries - intersections)) {
return (1);
} else
/*
* majority split
*/
if (intersections > (session->member_list_entries - intersections)) {
return (1);
}
return (0);
}
static int decide (void)
{
int i;
/*
* Determine if there is a subquorum
*/
if (subquorum (view_list, view_list_entries, last_primary_max) == 0) {
return (0);
}
for (i = 0; i < ambiguous_sessions_max_entries; i++) {
if (subquorum (view_list, view_list_entries, &ambiguous_sessions_max[i]) == 0) {
return (0);
}
-
+
}
return (1);
}
static void ykd_session_endian_convert (struct ykd_session *ykd_session)
{
int i;
ykd_session->member_list_entries =
swab32 (ykd_session->member_list_entries);
ykd_session->session_id = swab32 (ykd_session->session_id);
for (i = 0; i < ykd_session->member_list_entries; i++) {
ykd_session->member_list[i] =
swab32 (ykd_session->member_list[i]);
}
}
static void ykd_state_endian_convert (struct ykd_state *state)
{
int i;
ykd_session_endian_convert (&state->last_primary);
state->last_formed_entries = swab32 (state->last_formed_entries);
state->ambiguous_sessions_entries = swab32 (state->ambiguous_sessions_entries);
state->session_id = swab32 (state->session_id);
for (i = 0; i < state->last_formed_entries; i++) {
ykd_session_endian_convert (&state->last_formed[i]);
}
-
+
for (i = 0; i < state->ambiguous_sessions_entries; i++) {
ykd_session_endian_convert (&state->ambiguous_sessions[i]);
}
}
static void ykd_deliver_fn (
unsigned int nodeid,
const struct iovec *iovec,
unsigned int iov_len,
int endian_conversion_required)
{
int all_received = 1;
int state_position = 0;
int i;
char *msg_state = (char *)(iovec->iov_base) + sizeof (struct ykd_header);
-
+
/*
* If this is a localhost address, this node is always primary
*/
#ifdef TODO
if (totemip_localhost_check (source_addr)) {
log_printf (LOGSYS_LEVEL_NOTICE,
"This processor is within the primary component.\n");
primary_designated = 1;
ykd_primary_callback_fn (
view_list,
view_list_entries,
primary_designated,
&ykd_ring_id);
return;
}
#endif
if (endian_conversion_required &&
(iovec->iov_len > sizeof (struct ykd_header))) {
ykd_state_endian_convert ((struct ykd_state *)msg_state);
}
/*
* Set completion for source_addr's address
*/
for (state_position = 0; state_position < state_received_confchg_entries; state_position++) {
if (nodeid == state_received_process[state_position].nodeid) {
/*
* State position contains the address of the state to modify
* This may be used later by the other algorithms
*/
state_received_process[state_position].received = 1;
break;
}
}
/*
* Test if all nodes have submitted their state data
*/
for (i = 0; i < state_received_confchg_entries; i++) {
if (state_received_process[i].received == 0) {
all_received = 0;
}
}
switch (ykd_mode) {
case YKD_MODE_SENDSTATE:
assert (iovec->iov_len > sizeof (struct ykd_header));
/*
* Copy state information for the sending processor
*/
memcpy (&state_received_process[state_position].ykd_state,
msg_state, sizeof (struct ykd_state));
/*
* Try to form a component
*/
if (all_received) {
for (i = 0; i < state_received_confchg_entries; i++) {
state_received_process[i].received = 0;
}
ykd_mode = YKD_MODE_ATTEMPT;
// TODO resolve optimizes for failure conditions during ykd calculation
// resolve();
compute();
if (decide ()) {
ykd_state.session_id = session_id_max + 1;
memcpy (ykd_state.ambiguous_sessions[ykd_state.ambiguous_sessions_entries].member_list,
view_list, sizeof (unsigned int) * view_list_entries);
ykd_state.ambiguous_sessions[ykd_state.ambiguous_sessions_entries].member_list_entries = view_list_entries;
ykd_state.ambiguous_sessions_entries += 1;
ykd_attempt_send();
}
}
break;
case YKD_MODE_ATTEMPT:
if (all_received) {
log_printf (LOGSYS_LEVEL_NOTICE,
"This processor is within the primary component.\n");
primary_designated = 1;
ykd_primary_callback_fn (
view_list,
view_list_entries,
primary_designated,
&ykd_ring_id);
memcpy (ykd_state.last_primary.member_list, view_list, sizeof (view_list));
ykd_state.last_primary.member_list_entries = view_list_entries;
ykd_state.last_primary.session_id = ykd_state.session_id;
ykd_state.ambiguous_sessions_entries = 0;
}
break;
}
}
int first_run = 1;
static void ykd_confchg_fn (
enum totem_configuration_type configuration_type,
const unsigned int *member_list, size_t member_list_entries,
const unsigned int *left_list, size_t left_list_entries,
const unsigned int *joined_list, size_t joined_list_entries,
const struct memb_ring_id *ring_id)
{
int i;
if (configuration_type != TOTEM_CONFIGURATION_REGULAR) {
return;
}
memcpy (&ykd_ring_id, ring_id, sizeof (struct memb_ring_id));
if (first_run) {
ykd_state.last_primary.member_list[0] = api->totem_nodeid_get();
ykd_state.last_primary.member_list_entries = 1;
ykd_state.last_primary.session_id = 0;
first_run = 0;
}
memcpy (view_list, member_list,
member_list_entries * sizeof (unsigned int));
view_list_entries = member_list_entries;
ykd_mode = YKD_MODE_SENDSTATE;
primary_designated = 0;
ykd_primary_callback_fn (
view_list,
view_list_entries,
primary_designated,
&ykd_ring_id);
memset (&state_received_confchg, 0, sizeof (state_received_confchg));
for (i = 0; i < member_list_entries; i++) {
state_received_confchg[i].nodeid = member_list[i];
state_received_confchg[i].received = 0;
}
memcpy (state_received_process, state_received_confchg,
sizeof (state_received_confchg));
state_received_confchg_entries = member_list_entries;
state_received_process_entries = member_list_entries;
ykd_state_send ();
}
struct corosync_tpg_group ykd_group = {
.group = "ykd",
.group_len = 3
};
static void ykd_init (
struct corosync_api_v1 *corosync_api,
quorum_set_quorate_fn_t set_primary)
{
ykd_primary_callback_fn = set_primary;
api = corosync_api;
api->tpg_init (
&ykd_group_handle,
ykd_deliver_fn,
ykd_confchg_fn);
api->tpg_join (
ykd_group_handle,
&ykd_group,
1);
ykd_state_init ();
}
/*
* lcrso object definition
*/
static struct quorum_services_api_ver1 vsf_ykd_iface_ver0 = {
.init = ykd_init,
};
static struct lcr_iface corosync_vsf_ykd_ver0[1] = {
{
.name = "corosync_quorum_ykd",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = NULL,
.destructor = NULL,
.interfaces = (void **)(void *)&vsf_ykd_iface_ver0,
}
};
static struct lcr_comp vsf_ykd_comp_ver0 = {
.iface_count = 1,
.ifaces = corosync_vsf_ykd_ver0
};
__attribute__ ((constructor)) static void vsf_ykd_comp_register (void) {
lcr_component_register (&vsf_ykd_comp_ver0);
}
diff --git a/exec/wthread.c b/exec/wthread.c
index 791fb425..7cd2dbc7 100644
--- a/exec/wthread.c
+++ b/exec/wthread.c
@@ -1,215 +1,215 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Add work to a work group and have threads process the work
- * Provide blocking for all work to complete
+ * Provide blocking for all work to complete
*/
#include <config.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <corosync/queue.h>
#include "wthread.h"
struct thread_data {
void *thread_state;
void *data;
};
struct worker_thread_t {
struct worker_thread_group *worker_thread_group;
pthread_mutex_t new_work_mutex;
pthread_cond_t new_work_cond;
pthread_cond_t cond;
pthread_mutex_t done_work_mutex;
pthread_cond_t done_work_cond;
pthread_t thread_id;
struct queue queue;
void *thread_state;
struct thread_data thread_data;
};
static void *start_worker_thread (void *thread_data_in) {
struct thread_data *thread_data = (struct thread_data *)thread_data_in;
struct worker_thread_t *worker_thread =
(struct worker_thread_t *)thread_data->data;
void *data_for_worker_fn;
for (;;) {
pthread_mutex_lock (&worker_thread->new_work_mutex);
if (queue_is_empty (&worker_thread->queue) == 1) {
pthread_cond_wait (&worker_thread->new_work_cond,
&worker_thread->new_work_mutex);
}
/*
* We unlock then relock the new_work_mutex to allow the
* worker function to execute and also allow new work to be
* added to the work queue
*/
data_for_worker_fn = queue_item_get (&worker_thread->queue);
pthread_mutex_unlock (&worker_thread->new_work_mutex);
worker_thread->worker_thread_group->worker_fn (worker_thread->thread_state, data_for_worker_fn);
pthread_mutex_lock (&worker_thread->new_work_mutex);
queue_item_remove (&worker_thread->queue);
pthread_mutex_unlock (&worker_thread->new_work_mutex);
pthread_mutex_lock (&worker_thread->done_work_mutex);
if (queue_is_empty (&worker_thread->queue) == 1) {
pthread_cond_signal (&worker_thread->done_work_cond);
}
pthread_mutex_unlock (&worker_thread->done_work_mutex);
}
return (NULL);
}
int worker_thread_group_init (
struct worker_thread_group *worker_thread_group,
int threads,
int items_max,
int item_size,
int thread_state_size,
void (*thread_state_constructor)(void *),
void (*worker_fn)(void *thread_state, void *work_item))
{
int i;
worker_thread_group->threadcount = threads;
worker_thread_group->last_scheduled = 0;
worker_thread_group->worker_fn = worker_fn;
worker_thread_group->threads = malloc (sizeof (struct worker_thread_t) *
threads);
if (worker_thread_group->threads == 0) {
return (-1);
}
for (i = 0; i < threads; i++) {
if (thread_state_size) {
worker_thread_group->threads[i].thread_state = malloc (thread_state_size);
} else {
worker_thread_group->threads[i].thread_state = NULL;
}
if (thread_state_constructor) {
thread_state_constructor (worker_thread_group->threads[i].thread_state);
}
worker_thread_group->threads[i].worker_thread_group = worker_thread_group;
pthread_mutex_init (&worker_thread_group->threads[i].new_work_mutex, NULL);
pthread_cond_init (&worker_thread_group->threads[i].new_work_cond, NULL);
pthread_mutex_init (&worker_thread_group->threads[i].done_work_mutex, NULL);
pthread_cond_init (&worker_thread_group->threads[i].done_work_cond, NULL);
queue_init (&worker_thread_group->threads[i].queue, items_max,
item_size);
worker_thread_group->threads[i].thread_data.thread_state =
worker_thread_group->threads[i].thread_state;
worker_thread_group->threads[i].thread_data.data = &worker_thread_group->threads[i];
pthread_create (&worker_thread_group->threads[i].thread_id,
NULL, start_worker_thread, &worker_thread_group->threads[i].thread_data);
}
return (0);
}
int worker_thread_group_work_add (
struct worker_thread_group *worker_thread_group,
void *item)
{
int schedule;
schedule = (worker_thread_group->last_scheduled + 1) % (worker_thread_group->threadcount);
worker_thread_group->last_scheduled = schedule;
pthread_mutex_lock (&worker_thread_group->threads[schedule].new_work_mutex);
if (queue_is_full (&worker_thread_group->threads[schedule].queue)) {
pthread_mutex_unlock (&worker_thread_group->threads[schedule].new_work_mutex);
return (-1);
}
queue_item_add (&worker_thread_group->threads[schedule].queue, item);
pthread_cond_signal (&worker_thread_group->threads[schedule].new_work_cond);
pthread_mutex_unlock (&worker_thread_group->threads[schedule].new_work_mutex);
return (0);
}
void worker_thread_group_wait (
struct worker_thread_group *worker_thread_group)
{
int i;
for (i = 0; i < worker_thread_group->threadcount; i++) {
pthread_mutex_lock (&worker_thread_group->threads[i].done_work_mutex);
if (queue_is_empty (&worker_thread_group->threads[i].queue) == 0) {
pthread_cond_wait (&worker_thread_group->threads[i].done_work_cond,
&worker_thread_group->threads[i].done_work_mutex);
}
pthread_mutex_unlock (&worker_thread_group->threads[i].done_work_mutex);
}
}
void worker_thread_group_exit (
struct worker_thread_group *worker_thread_group)
{
int i;
for (i = 0; i < worker_thread_group->threadcount; i++) {
pthread_cancel (worker_thread_group->threads[i].thread_id);
/* Wait for worker thread to exit gracefully before destroying
* mutexes and processing items in the queue etc.
*/
pthread_join (worker_thread_group->threads[i].thread_id, NULL);
pthread_mutex_destroy (&worker_thread_group->threads[i].new_work_mutex);
pthread_cond_destroy (&worker_thread_group->threads[i].new_work_cond);
pthread_mutex_destroy (&worker_thread_group->threads[i].done_work_mutex);
pthread_cond_destroy (&worker_thread_group->threads[i].done_work_cond);
}
}
void worker_thread_group_atsegv (
struct worker_thread_group *worker_thread_group)
{
void *data_for_worker_fn;
struct worker_thread_t *worker_thread;
unsigned int i;
for (i = 0; i < worker_thread_group->threadcount; i++) {
worker_thread = &worker_thread_group->threads[i];
while (queue_is_empty (&worker_thread->queue) == 0) {
data_for_worker_fn = queue_item_get (&worker_thread->queue);
worker_thread->worker_thread_group->worker_fn (worker_thread->thread_state, data_for_worker_fn);
queue_item_remove (&worker_thread->queue);
}
}
}
diff --git a/exec/wthread.h b/exec/wthread.h
index 374897e9..ef89594c 100644
--- a/exec/wthread.h
+++ b/exec/wthread.h
@@ -1,67 +1,67 @@
/*
* Copyright (c) 2005 MontaVista Software, 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.
*/
#ifndef CONFIG_WTHREAD_H_DEFINED
#define CONFIG_WTHREAD_H_DEFINED
struct worker_thread_group {
int threadcount;
int last_scheduled;
struct worker_thread_t *threads;
void (*worker_fn) (void *thread_state, void *work_item);
};
extern int worker_thread_group_init (
struct worker_thread_group *worker_thread_group,
int threads,
int items_max,
int item_size,
int thread_state_size,
void (*thread_state_constructor)(void *),
void (*worker_fn)(void *thread_state, void *work_item));
extern int worker_thread_group_work_add (
struct worker_thread_group *worker_thread_group,
void *item);
extern void worker_thread_group_wait (
struct worker_thread_group *worker_thread_group);
extern void worker_thread_group_exit (
struct worker_thread_group *worker_thread_group);
extern void worker_thread_group_atsegv (
struct worker_thread_group *worker_thread_group);
#endif /* WTHREAD_H_DEFINED */
diff --git a/include/Makefile.am b/include/Makefile.am
index a4c8c868..908558a4 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,53 +1,53 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in corosync/config.h.in
CS_H = hdb.h cs_config.h cpg.h cfg.h evs.h ipc_gen.h mar_gen.h swab.h \
coroipcc.h confdb.h list.h corotypes.h quorum.h votequorum.h
CS_INTERNAL_H = ipc_cfg.h ipc_confdb.h ipc_cpg.h ipc_evs.h ipc_pload.h ipc_quorum.h \
jhash.h mar_cpg.h pload.h queue.h quorum.h rmd.h sq.h ipc_votequorum.h
LCR_H = lcr_ckpt.h lcr_comp.h lcr_ifact.h
ENGINE_H = config.h coroapi.h logsys.h objdb.h quorum.h
TOTEM_H = coropoll.h totem.h totemip.h totempg.h
EXTRA_DIST = $(noinst_HEADERS)
-noinst_HEADERS = $(CS_INTERNAL_H:%=corosync/%)
+noinst_HEADERS = $(CS_INTERNAL_H:%=corosync/%)
nobase_include_HEADERS = $(CS_H:%=corosync/%) $(LCR_H:%=corosync/lcr/%) \
$(ENGINE_H:%=corosync/engine/%) $(TOTEM_H:%=corosync/totem/%)
diff --git a/include/corosync/cfg.h b/include/corosync/cfg.h
index f50a7918..04d3dbc5 100644
--- a/include/corosync/cfg.h
+++ b/include/corosync/cfg.h
@@ -1,235 +1,235 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AIS_COROSYNCCFG_H_DEFINED
#define AIS_COROSYNCCFG_H_DEFINED
#include <netinet/in.h>
#include <corosync/corotypes.h>
typedef uint64_t corosync_cfg_handle_t;
typedef enum {
COROSYNC_CFG_ADMINISTRATIVETARGET_SERVICEUNIT = 0,
COROSYNC_CFG_ADMINISTRATIVETARGET_SERVICEGROUP = 1,
COROSYNC_CFG_ADMINISTRATIVETARGET_COMPONENTSERVICEINSTANCE = 2,
COROSYNC_CFG_ADMINISTRATIVETARGET_NODE = 3
} corosync_cfg_administrative_target_t;
typedef enum {
COROSYNC_CFG_ADMINISTRATIVESTATE_UNLOCKED = 0,
COROSYNC_CFG_ADMINISTRATIVESTATE_LOCKED = 1,
COROSYNC_CFG_ADMINISTRATIVESTATE_STOPPING = 2
} corosync_cfg_administrative_state_t;
typedef enum {
COROSYNC_CFG_OPERATIONALSTATE_ENABLED = 1,
COROSYNC_CFG_OPERATIONALSTATE_DISABLED = 2
} corosync_cfg_operational_state_t;
typedef enum {
COROSYNC_CFG_READINESSSTATE_OUTOFSERVICE = 1,
COROSYNC_CFG_READINESSSTATE_INSERVICE = 2,
COROSYNC_CFG_READINESSSTATE_STOPPING = 3
} corosync_cfg_readiness_state_t;
typedef enum {
COROSYNC_CFG_PRESENCESTATE_UNINSTANTIATED = 1,
COROSYNC_CFG_PRESENCESTATE_INSTANTIATING = 2,
COROSYNC_CFG_PRESENCESTATE_INSTANTIATED = 3,
COROSYNC_CFG_PRESENCESTATE_TERMINATING = 4,
COROSYNC_CFG_PRESENCESTATE_RESTARTING = 5,
COROSYNC_CFG_PRESENCESTATE_INSTANTIATION_FAILED = 6,
COROSYNC_CFG_PRESENCESTATE_TERMINATION_FAILED = 7
} corosync_cfg_presence_state_t;
typedef enum {
COROSYNC_CFG_STATETYPE_OPERATIONAL = 0,
COROSYNC_CFG_STATETYPE_ADMINISTRATIVE = 1,
COROSYNC_CFG_STATETYPE_READINESS = 2,
COROSYNC_CFG_STATETYPE_HA = 3,
COROSYNC_CFG_STATETYPE_PRESENCE = 4
} corosync_cfg_state_type_t;
/* Shutdown types.
REQUEST is the normal shutdown. other daemons will be consulted
REGARDLESS will tell other daemons but ignore their opinions
IMMEDIATE will shut down straight away (but still tell other nodes)
*/
typedef enum {
COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST = 0,
COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS = 1,
COROSYNC_CFG_SHUTDOWN_FLAG_IMMEDIATE = 2,
} corosync_cfg_shutdown_flags_t;
typedef enum {
COROSYNC_CFG_SHUTDOWN_FLAG_NO = 0,
COROSYNC_CFG_SHUTDOWN_FLAG_YES = 1,
} corosync_cfg_shutdown_reply_flags_t;
typedef struct {
cs_name_t name;
corosync_cfg_state_type_t state_type;
corosync_cfg_administrative_state_t administrative_state;
} corosync_cfg_state_notification_t;
typedef struct {
uint32_t number_of_items;
corosync_cfg_state_notification_t *notification;
} corosync_cfg_state_notification_buffer_t;
typedef void (*corosync_cfg_state_track_callback_t) (
corosync_cfg_state_notification_buffer_t *notification_buffer,
cs_error_t error);
typedef void (*corosync_cfg_shutdown_callback_t) (
corosync_cfg_handle_t cfg_handle,
corosync_cfg_shutdown_flags_t flags);
typedef struct {
corosync_cfg_state_track_callback_t corosync_cfg_state_track_callback;
corosync_cfg_shutdown_callback_t corosync_cfg_shutdown_callback;
} corosync_cfg_callbacks_t;
/*
* A node address. This is a complete sockaddr_in[6]
* To explain:
* If you cast cna_address to a 'struct sockaddr', the sa_family field
* will be AF_INET or AF_INET6. Armed with that knowledge you can then
* cast it to a sockaddr_in or sockaddr_in6 and pull out the address.
* No other sockaddr fields are valid.
* Also, you must ignore any part of the sockaddr beyond the length supplied
*/
typedef struct
{
int address_length; /* FIXME: set but never used */
char address[sizeof(struct sockaddr_in6)];
} corosync_cfg_node_address_t;
/*
* Interfaces
*/
#ifdef __cplusplus
extern "C" {
#endif
cs_error_t
corosync_cfg_initialize (
corosync_cfg_handle_t *cfg_handle,
const corosync_cfg_callbacks_t *cfg_callbacks);
cs_error_t
corosync_cfg_fd_get (
corosync_cfg_handle_t cfg_handle,
int32_t *selection_fd);
cs_error_t
corosync_cfg_dispatch (
corosync_cfg_handle_t cfg_handle,
cs_dispatch_flags_t dispatch_flags);
cs_error_t
corosync_cfg_finalize (
corosync_cfg_handle_t cfg_handle);
cs_error_t
corosync_cfg_ring_status_get (
corosync_cfg_handle_t cfg_handle,
char ***interface_names,
char ***status,
unsigned int *interface_count);
cs_error_t
corosync_cfg_ring_reenable (
corosync_cfg_handle_t cfg_handle);
cs_error_t
corosync_cfg_service_load (
corosync_cfg_handle_t cfg_handle,
const char *service_name,
unsigned int service_ver);
cs_error_t
corosync_cfg_service_unload (
corosync_cfg_handle_t cfg_handle,
const char *service_name,
unsigned int service_ver);
cs_error_t
corosync_cfg_kill_node (
corosync_cfg_handle_t cfg_handle,
unsigned int nodeid,
const char *reason);
cs_error_t
corosync_cfg_try_shutdown (
corosync_cfg_handle_t cfg_handle,
corosync_cfg_shutdown_flags_t flags);
cs_error_t
corosync_cfg_replyto_shutdown (
corosync_cfg_handle_t cfg_handle,
corosync_cfg_shutdown_reply_flags_t flags);
cs_error_t
corosync_cfg_state_track (
corosync_cfg_handle_t cfg_handle,
uint8_t track_flags,
const corosync_cfg_state_notification_t *notification_buffer);
cs_error_t
corosync_cfg_state_track_stop (
corosync_cfg_handle_t cfg_handle);
cs_error_t
corosync_cfg_get_node_addrs (
corosync_cfg_handle_t cfg_handle,
int nodeid,
size_t max_addrs,
int *num_addrs,
corosync_cfg_node_address_t *addrs);
cs_error_t
corosync_cfg_local_get (
corosync_cfg_handle_t handle,
unsigned int *local_nodeid);
#ifdef __cplusplus
}
#endif
#endif /* AIS_COROSYNCCFG_H_DEFINED */
diff --git a/include/corosync/coroipcc.h b/include/corosync/coroipcc.h
index 2c7fc2e8..99dbf0a3 100644
--- a/include/corosync/coroipcc.h
+++ b/include/corosync/coroipcc.h
@@ -1,162 +1,162 @@
/*
* Copyright (c) 2002-2003 MontaVista Software, Inc.
* Copyright (c) 2006-2007, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COROIPC_H_DEFINED
#define COROIPC_H_DEFINED
#include <config.h>
#include <pthread.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <corosync/corotypes.h>
#include <corosync/ipc_gen.h>
extern cs_error_t
coroipcc_service_connect (
const char *socket_name,
unsigned int service,
size_t request_size,
size_t respnse__size,
size_t dispatch_size,
void **ipc_context);
extern cs_error_t
coroipcc_service_disconnect (
void *ipc_context);
extern int
coroipcc_fd_get (
void *ipc_context);
extern int
coroipcc_dispatch_get (
void *ipc_context,
void **buf,
int timeout);
extern int
coroipcc_dispatch_put (
void *ipc_context);
extern int
coroipcc_dispatch_flow_control_get (
void *ipc_context);
extern cs_error_t
coroipcc_msg_send_reply_receive (
void *ipc_context,
const struct iovec *iov,
unsigned int iov_len,
void *res_msg,
size_t res_len);
extern cs_error_t
coroipcc_msg_send_reply_receive_in_buf (
void *ipc_context,
const struct iovec *iov,
unsigned int iov_len,
void **res_msg);
extern cs_error_t
coroipcc_zcb_alloc (
void *ipc_context,
void **buffer,
size_t size,
size_t header_size);
extern cs_error_t
coroipcc_zcb_free (
void *ipc_context,
void *buffer);
extern cs_error_t
coroipcc_zcb_msg_send_reply_receive (
void *ipc_context,
void *msg,
void *res_msg,
size_t res_len);
/*
* TODO This needs to be removed
*/
struct saHandleDatabase {
unsigned int handleCount;
struct saHandle *handles;
#if defined(HAVE_PTHREAD_SPIN_LOCK)
pthread_spinlock_t lock;
#else
pthread_mutex_t lock;
#endif
void (*handleInstanceDestructor) (void *);
};
extern void saHandleDatabaseLock_init (struct saHandleDatabase *hdb);
#define DECLARE_SAHDB_DATABASE(database_name,destructor) \
static struct saHandleDatabase (database_name) = { \
.handleInstanceDestructor = destructor, \
.handleCount = 0, \
.handles = NULL, \
}; \
static void database_name##_init(void)__attribute__((constructor)); \
static void database_name##_init(void) \
{ \
saHandleDatabaseLock_init (&(database_name)); \
}
extern cs_error_t
saHandleCreate (
struct saHandleDatabase *handleDatabase,
int instanceSize,
uint64_t *handleOut);
extern cs_error_t
saHandleDestroy (
struct saHandleDatabase *handleDatabase,
uint64_t handle);
extern cs_error_t
saHandleInstanceGet (
struct saHandleDatabase *handleDatabase,
uint64_t handle,
void **instance);
extern cs_error_t
saHandleInstancePut (
struct saHandleDatabase *handleDatabase,
uint64_t handle);
#endif /* COROIPC_H_DEFINED */
diff --git a/include/corosync/corotypes.h b/include/corosync/corotypes.h
index 75f45a5b..98001b24 100644
--- a/include/corosync/corotypes.h
+++ b/include/corosync/corotypes.h
@@ -1,180 +1,180 @@
/*
* Copyright (c) 2008 Allied Telesis Labs.
*
* All rights reserved.
*
* Author: Angus Salkeld (ahsalkeld@gmail.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.
*/
#ifndef COROTYPES_H_DEFINED
#define COROTYPES_H_DEFINED
#ifndef COROSYNC_SOLARIS
#include <stdint.h>
#else
#include <sys/types.h>
#endif
typedef int64_t cs_time_t;
#define CS_FALSE 0
#define CS_TRUE !CS_FALSE
#define CS_MAX_NAME_LENGTH 256
#define CS_TIME_END ((cs_time_t)0x7FFFFFFFFFFFFFFFULL)
typedef struct {
uint16_t length;
uint8_t value[CS_MAX_NAME_LENGTH];
} cs_name_t;
typedef struct {
char releaseCode;
unsigned char majorVersion;
unsigned char minorVersion;
} cs_version_t;
typedef enum {
CS_DISPATCH_ONE = 1,
CS_DISPATCH_ALL = 2,
CS_DISPATCH_BLOCKING = 3
} cs_dispatch_flags_t;
#define CS_TRACK_CURRENT 0x01
#define CS_TRACK_CHANGES 0x02
#define CS_TRACK_CHANGES_ONLY 0x04
typedef enum {
CS_OK = 1,
CS_ERR_LIBRARY = 2,
CS_ERR_VERSION = 3,
CS_ERR_INIT = 4,
CS_ERR_TIMEOUT = 5,
CS_ERR_TRY_AGAIN = 6,
CS_ERR_INVALID_PARAM = 7,
CS_ERR_NO_MEMORY = 8,
CS_ERR_BAD_HANDLE = 9,
CS_ERR_BUSY = 10,
CS_ERR_ACCESS = 11,
CS_ERR_NOT_EXIST = 12,
CS_ERR_NAME_TOO_LONG = 13,
CS_ERR_EXIST = 14,
CS_ERR_NO_SPACE = 15,
CS_ERR_INTERRUPT = 16,
CS_ERR_NAME_NOT_FOUND = 17,
CS_ERR_NO_RESOURCES = 18,
CS_ERR_NOT_SUPPORTED = 19,
CS_ERR_BAD_OPERATION = 20,
CS_ERR_FAILED_OPERATION = 21,
CS_ERR_MESSAGE_ERROR = 22,
CS_ERR_QUEUE_FULL = 23,
CS_ERR_QUEUE_NOT_AVAILABLE = 24,
CS_ERR_BAD_FLAGS = 25,
CS_ERR_TOO_BIG = 26,
CS_ERR_NO_SECTIONS = 27,
CS_ERR_CONTEXT_NOT_FOUND = 28,
CS_ERR_SECURITY = 29,
CS_ERR_TOO_MANY_GROUPS = 30
} cs_error_t;
/*
* DEPRECATED
*/
#define EVS_DISPATCH_ONE CS_DISPATCH_ONE
#define EVS_DISPATCH_ALL CS_DISPATCH_ALL
#define EVS_DISPATCH_BLOCKING CS_DISPATCH_BLOCKING
#define EVS_OK CS_OK
#define EVS_ERR_LIBRARY CS_ERR_LIBRARY
#define EVS_ERR_TIMEOUT CS_ERR_TIMEOUT
#define EVS_ERR_TRY_AGAIN CS_ERR_TRY_AGAIN
#define EVS_ERR_INVALID_PARAM CS_ERR_INVALID_PARAM
#define EVS_ERR_NO_MEMORY CS_ERR_NO_MEMORY
#define EVS_ERR_BAD_HANDLE CS_ERR_BAD_HANDLE
#define EVS_ERR_ACCESS CS_ERR_ACCESS
#define EVS_ERR_NOT_EXIST CS_ERR_NOT_EXIST
#define EVS_ERR_EXIST CS_ERR_EXIST
#define EVS_ERR_NOT_SUPPORTED CS_ERR_NOT_SUPPORTED
#define EVS_ERR_SECURITY CS_ERR_SECURITY
#define EVS_ERR_TOO_MANY_GROUPS CS_ERR_TOO_MANY_GROUPS
#define evs_error_t cs_error_t
#define CPG_DISPATCH_ONE CS_DISPATCH_ONE
#define CPG_DISPATCH_ALL CS_DISPATCH_ALL
#define CPG_DISPATCH_BLOCKING CS_DISPATCH_BLOCKING
#define CPG_OK CS_OK
#define CPG_ERR_LIBRARY CS_ERR_LIBRARY
#define CPG_ERR_TIMEOUT CS_ERR_TIMEOUT
#define CPG_ERR_TRY_AGAIN CS_ERR_TRY_AGAIN
#define CPG_ERR_INVALID_PARAM CS_ERR_INVALID_PARAM
#define CPG_ERR_NO_MEMORY CS_ERR_NO_MEMORY
#define CPG_ERR_BAD_HANDLE CS_ERR_BAD_HANDLE
#define CPG_ERR_ACCESS CS_ERR_ACCESS
#define CPG_ERR_NOT_EXIST CS_ERR_NOT_EXIST
#define CPG_ERR_EXIST CS_ERR_EXIST
#define CPG_ERR_NOT_SUPPORTED CS_ERR_NOT_SUPPORTED
#define CPG_ERR_SECURITY CS_ERR_SECURITY
#define CPG_ERR_TOO_MANY_GROUPS CS_ERR_TOO_MANY_GROUPS
#define cpg_error_t cs_error_t
#define CONFDB_DISPATCH_ONE CS_DISPATCH_ONE
#define CONFDB_DISPATCH_ALL CS_DISPATCH_ALL
#define CONFDB_DISPATCH_BLOCKING CS_DISPATCH_BLOCKING
#define CONFDB_OK CS_OK
#define CONFDB_ERR_LIBRARY CS_ERR_LIBRARY
#define CONFDB_ERR_TIMEOUT CS_ERR_TIMEOUT
#define CONFDB_ERR_TRY_AGAIN CS_ERR_TRY_AGAIN
#define CONFDB_ERR_INVALID_PARAM CS_ERR_INVALID_PARAM
#define CONFDB_ERR_NO_MEMORY CS_ERR_NO_MEMORY
#define CONFDB_ERR_BAD_HANDLE CS_ERR_BAD_HANDLE
#define CONFDB_ERR_ACCESS CS_ERR_ACCESS
#define CONFDB_ERR_NOT_EXIST CS_ERR_NOT_EXIST
#define CONFDB_ERR_EXIST CS_ERR_EXIST
#define CONFDB_ERR_NOT_SUPPORTED CS_ERR_NOT_SUPPORTED
#define CONFDB_ERR_SECURITY CS_ERR_SECURITY
#define confdb_error_t cs_error_t
#define QUORUM_DISPATCH_ONE CS_DISPATCH_ONE
#define QUORUM_DISPATCH_ALL CS_DISPATCH_ALL
#define QUORUM_DISPATCH_BLOCKING CS_DISPATCH_BLOCKING
#define QUORUM_OK CS_OK
#define QUORUM_ERR_LIBRARY CS_ERR_LIBRARY
#define QUORUM_ERR_TIMEOUT CS_ERR_TIMEOUT
#define QUORUM_ERR_TRY_AGAIN CS_ERR_TRY_AGAIN
#define QUORUM_ERR_INVALID_PARAM CS_ERR_INVALID_PARAM
#define QUORUM_ERR_NO_MEMORY CS_ERR_NO_MEMORY
#define QUORUM_ERR_BAD_HANDLE CS_ERR_BAD_HANDLE
#define QUORUM_ERR_ACCESS CS_ERR_ACCESS
#define QUORUM_ERR_NOT_EXIST CS_ERR_NOT_EXIST
#define QUORUM_ERR_EXIST CS_ERR_EXIST
#define QUORUM_ERR_NOT_SUPPORTED CS_ERR_NOT_SUPPORTED
#define QUORUM_ERR_SECURITY CS_ERR_SECURITY
#define quorum_error_t cs_error_t
#endif
diff --git a/include/corosync/engine/config.h b/include/corosync/engine/config.h
index 343c9718..e7c8deda 100644
--- a/include/corosync/engine/config.h
+++ b/include/corosync/engine/config.h
@@ -1,46 +1,46 @@
/*
* Copyright (c) 2006 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Patrick Caulfield (pcaulfie@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.
*/
#ifndef CONFIG_H_DEFINED
#define CONFIG_H_DEFINED
struct config_iface_ver0 {
int (*config_readconfig) (struct objdb_iface_ver0 *objdb, const char **error_string);
int (*config_writeconfig) (struct objdb_iface_ver0 *objdb, const char **error_string);
int (*config_reloadconfig) (struct objdb_iface_ver0 *objdb, int flush, const char **error_string);
};
#endif /* CONFIG_H_DEFINED */
diff --git a/include/corosync/engine/logsys.h b/include/corosync/engine/logsys.h
index 7071f298..f191de2b 100644
--- a/include/corosync/engine/logsys.h
+++ b/include/corosync/engine/logsys.h
@@ -1,345 +1,345 @@
/*
* Copyright (c) 2002-2004 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* Author: Steven Dake (sdake@redhat.com)
* Author: Lon Hohberger (lhh@redhat.com)
* Author: Fabio M. Di Nitto (fdinitto@redhat.com)
*
* All rights reserved.
*
* 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.
*/
#ifndef LOGSYS_H_DEFINED
#define LOGSYS_H_DEFINED
#include <stdarg.h>
#include <syslog.h>
#include <assert.h>
/*
* All of the LOGSYS_MODE's can be ORed together for combined behavior
*
* FORK and THREADED are ignored for SUBSYSTEMS
*/
#define LOGSYS_MODE_OUTPUT_FILE (1<<0)
#define LOGSYS_MODE_OUTPUT_STDERR (1<<1)
#define LOGSYS_MODE_OUTPUT_SYSLOG (1<<2)
#define LOGSYS_MODE_FORK (1<<3)
#define LOGSYS_MODE_THREADED (1<<4)
/*
* Log priorities, compliant with syslog and SA Forum Log spec.
*/
#define LOGSYS_LEVEL_EMERG LOG_EMERG
#define LOGSYS_LEVEL_ALERT LOG_ALERT
#define LOGSYS_LEVEL_CRIT LOG_CRIT
#define LOGSYS_LEVEL_ERROR LOG_ERR
#define LOGSYS_LEVEL_WARNING LOG_WARNING
#define LOGSYS_LEVEL_SECURITY LOG_WARNING // corosync specific
#define LOGSYS_LEVEL_NOTICE LOG_NOTICE
#define LOGSYS_LEVEL_INFO LOG_INFO
#define LOGSYS_LEVEL_DEBUG LOG_DEBUG
/*
* The tag masks are all mutually exclusive
*
* LOG is mandatory, but enforced, for subsystems.
* Be careful if/when changing tags at runtime.
*/
#define LOGSYS_TAG_LOG (0xff<<28)
#define LOGSYS_TAG_ENTER (1<<27)
#define LOGSYS_TAG_LEAVE (1<<26)
#define LOGSYS_TAG_TRACE1 (1<<25)
#define LOGSYS_TAG_TRACE2 (1<<24)
#define LOGSYS_TAG_TRACE3 (1<<23)
#define LOGSYS_TAG_TRACE4 (1<<22)
#define LOGSYS_TAG_TRACE5 (1<<21)
#define LOGSYS_TAG_TRACE6 (1<<20)
#define LOGSYS_TAG_TRACE7 (1<<19)
#define LOGSYS_TAG_TRACE8 (1<<18)
/*
* Internal APIs that must be globally exported
* (External API below)
*/
/*
* logsys_logger bits
*
* SUBSYS_COUNT defines the maximum number of subsystems
* SUBSYS_NAMELEN defines the maximum len of a subsystem name
*/
#define LOGSYS_MAX_SUBSYS_COUNT 64
#define LOGSYS_MAX_SUBSYS_NAMELEN 64
extern int _logsys_system_setup(
const char *mainsystem,
unsigned int mode,
unsigned int debug,
const char *logfile,
int logfile_priority,
int syslog_facility,
int syslog_priority,
unsigned int tags);
extern int _logsys_config_subsys_get (
const char *subsys);
extern unsigned int _logsys_subsys_create (const char *subsys);
extern int _logsys_rec_init (unsigned int size);
extern void _logsys_log_printf (
int subsysid,
const char *function_name,
const char *file_name,
int file_line,
unsigned int level,
const char *format,
...) __attribute__((format(printf, 6, 7)));
extern void _logsys_log_rec (
int subsysid,
const char *function_name,
const char *file_name,
int file_line,
unsigned int rec_ident,
...);
extern int _logsys_wthread_create (void);
static unsigned int logsys_subsys_id __attribute__((unused)) = -1;
/*
* External API - init
* See below:
*
* LOGSYS_DECLARE_SYSTEM
* LOGSYS_DECLARE_SUBSYS
*
*/
extern void logsys_fork_completed (void);
extern void logsys_atexit (void);
/*
* External API - misc
*/
extern void logsys_flush (void);
extern int logsys_log_rec_store (const char *filename);
/*
* External API - configuration
*/
/*
* configuration bits that can only be done for the whole system
*/
extern int logsys_format_set (
const char *format);
extern char *logsys_format_get (void);
/*
* per system/subsystem settings.
*
* NOTE: once a subsystem is created and configured, changing
* the default does NOT affect the subsystems.
*
* Pass a NULL subsystem to change them all
*/
extern unsigned int logsys_config_syslog_facility_set (
const char *subsys,
unsigned int facility);
extern unsigned int logsys_config_syslog_priority_set (
const char *subsys,
unsigned int priority);
extern unsigned int logsys_config_mode_set (
const char *subsys,
unsigned int mode);
extern unsigned int logsys_config_mode_get (
const char *subsys);
extern unsigned int logsys_config_tags_set (
const char *subsys,
unsigned int tags);
extern unsigned int logsys_config_tags_get (
const char *subsys);
/*
* to close a logfile, just invoke this function with a NULL
* file or if you want to change logfile, the old one will
* be closed for you.
*/
extern int logsys_config_file_set (
const char *subsys,
const char **error_string,
const char *file);
extern unsigned int logsys_config_logfile_priority_set (
const char *subsys,
unsigned int priority);
/*
* enabling debug, disable message priority filtering.
* everything is sent everywhere. priority values
* for file and syslog are not overwritten.
*/
extern unsigned int logsys_config_debug_set (
const char *subsys,
unsigned int value);
/*
* External API - helpers
*
* convert facility/priority/tag to/from name/values
*/
extern int logsys_facility_id_get (
const char *name);
extern const char *logsys_facility_name_get (
unsigned int facility);
extern int logsys_priority_id_get (
const char *name);
extern const char *logsys_priority_name_get (
unsigned int priority);
extern int logsys_tag_id_get (
const char *name);
extern const char *logsys_tag_name_get (
unsigned int tag);
/*
* External definitions
*/
extern void *logsys_rec_end;
#define LOGSYS_REC_END (&logsys_rec_end)
#define LOGSYS_DECLARE_SYSTEM(name,mode,debug,file,file_priority, \
syslog_facility,syslog_priority,tags,format,rec_size) \
__attribute__ ((constructor)) \
static void logsys_system_init (void) \
{ \
int err; \
\
err = _logsys_system_setup (name,mode,debug,file,file_priority, \
syslog_facility,syslog_priority,tags); \
assert (err == 0 && "_logsys_system_setup failed"); \
\
err = logsys_format_set (format); \
assert (err == 0 && "logsys_format_set failed"); \
\
err = _logsys_rec_init (rec_size); \
assert (err == 0 && "_logsys_rec_init failed"); \
\
err = _logsys_wthread_create(); \
assert (err == 0 && "_logsys_wthread_create failed"); \
}
#define LOGSYS_DECLARE_SUBSYS(subsys) \
__attribute__ ((constructor)) \
static void logsys_subsys_init (void) \
{ \
logsys_subsys_id = \
_logsys_subsys_create ((subsys)); \
assert (logsys_subsys_id < LOGSYS_MAX_SUBSYS_COUNT && \
"_logsys_subsys_create failed"); \
}
#define log_rec(rec_ident, args...) \
do { \
_logsys_log_rec (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, rec_ident, ##args); \
} while(0)
#define log_printf(lvl, format, args...) \
do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, lvl, format, ##args); \
} while(0)
#define ENTER() do { \
_logsys_log_rec (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_ENTER, LOGSYS_REC_END); \
} while(0)
#define LEAVE() do { \
_logsys_log_rec (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_LEAVE, LOGSYS_REC_END); \
} while(0)
#define TRACE1(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE1, format, ##args);\
} while(0)
#define TRACE2(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE2, format, ##args);\
} while(0)
#define TRACE3(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE3, format, ##args);\
} while(0)
#define TRACE4(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE4, format, ##args);\
} while(0)
#define TRACE5(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE5, format, ##args);\
} while(0)
#define TRACE6(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE6, format, ##args);\
} while(0)
#define TRACE7(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE7, format, ##args);\
} while(0)
#define TRACE8(format, args...) do { \
_logsys_log_printf (logsys_subsys_id, __FUNCTION__, \
__FILE__, __LINE__, LOGSYS_TAG_TRACE8, format, ##args);\
} while(0)
#endif /* LOGSYS_H_DEFINED */
diff --git a/include/corosync/engine/objdb.h b/include/corosync/engine/objdb.h
index ce401a98..d26b6f7c 100644
--- a/include/corosync/engine/objdb.h
+++ b/include/corosync/engine/objdb.h
@@ -1,240 +1,240 @@
/*
* Copyright (c) 2006 MontaVista Software, Inc.
* Copyright (c) 2007-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OBJDB_H_DEFINED
#define OBJDB_H_DEFINED
-#define OBJECT_PARENT_HANDLE 0xFFFFFFFF00000000ULL
+#define OBJECT_PARENT_HANDLE 0xFFFFFFFF00000000ULL
#include <stdio.h>
#include <corosync/hdb.h>
typedef enum {
OBJECT_TRACK_DEPTH_ONE,
OBJECT_TRACK_DEPTH_RECURSIVE
} object_track_depth_t;
typedef enum {
OBJECT_KEY_CREATED,
OBJECT_KEY_REPLACED,
OBJECT_KEY_DELETED
} object_change_type_t;
typedef enum {
OBJDB_RELOAD_NOTIFY_START,
OBJDB_RELOAD_NOTIFY_END,
OBJDB_RELOAD_NOTIFY_FAILED
} objdb_reload_notify_type_t;
typedef void (*object_key_change_notify_fn_t)(
object_change_type_t change_type,
hdb_handle_t parent_object_handle,
hdb_handle_t object_handle,
const void *object_name_pt, size_t object_name_len,
const void *key_name_pt, size_t key_len,
const void *key_value_pt, size_t key_value_len,
void *priv_data_pt);
typedef void (*object_create_notify_fn_t) (unsigned int parent_object_handle,
hdb_handle_t object_handle,
const void *name_pt, size_t name_len,
void *priv_data_pt);
typedef void (*object_destroy_notify_fn_t) (unsigned int parent_object_handle,
const void *name_pt,
size_t name_len,
void *priv_data_pt);
typedef void (*object_reload_notify_fn_t) (objdb_reload_notify_type_t, int flush,
void *priv_data_pt);
struct object_valid {
char *object_name;
size_t object_len;
};
struct object_key_valid {
char *key_name;
size_t key_len;
int (*validate_callback) (const void *key, size_t key_len,
const void *value, size_t value_len);
};
struct objdb_iface_ver0 {
int (*objdb_init) (void);
int (*object_create) (
hdb_handle_t parent_object_handle,
hdb_handle_t *object_handle,
const void *object_name,
size_t object_name_len);
int (*object_priv_set) (
hdb_handle_t object_handle,
void *priv);
int (*object_key_create) (
hdb_handle_t object_handle,
const void *key_name,
size_t key_len,
const void *value,
size_t value_len);
int (*object_destroy) (
hdb_handle_t object_handle);
int (*object_valid_set) (
hdb_handle_t object_handle,
struct object_valid *object_valid_list,
size_t object_valid_list_entries);
int (*object_key_valid_set) (
hdb_handle_t object_handle,
struct object_key_valid *object_key_valid_list,
size_t object_key_valid_list_entries);
int (*object_find_create) (
hdb_handle_t parent_object_handle,
const void *object_name,
size_t object_name_len,
hdb_handle_t *object_find_handle);
int (*object_find_next) (
hdb_handle_t object_find_handle,
hdb_handle_t *object_handle);
int (*object_find_destroy) (
hdb_handle_t object_find_handle);
int (*object_key_get) (
hdb_handle_t object_handle,
const void *key_name,
size_t key_len,
void **value,
size_t *value_len);
int (*object_priv_get) (
hdb_handle_t jobject_handle,
void **priv);
int (*object_key_replace) (
hdb_handle_t object_handle,
const void *key_name,
size_t key_len,
const void *new_value,
size_t new_value_len);
int (*object_key_delete) (
hdb_handle_t object_handle,
const void *key_name,
size_t key_len);
int (*object_iter_reset) (
hdb_handle_t parent_object_handle);
int (*object_iter) (
hdb_handle_t parent_object_handle,
void **object_name,
size_t *name_len,
hdb_handle_t *object_handle);
int (*object_key_iter_reset) (
hdb_handle_t object_handle);
int (*object_key_iter) (
hdb_handle_t parent_object_handle,
void **key_name,
size_t *key_len,
void **value,
size_t *value_len);
int (*object_parent_get) (
hdb_handle_t object_handle,
hdb_handle_t *parent_handle);
int (*object_name_get) (
hdb_handle_t object_handle,
char *object_name,
size_t *object_name_len);
int (*object_dump) (
hdb_handle_t object_handle,
FILE *file);
int (*object_key_iter_from) (
hdb_handle_t parent_object_handle,
hdb_handle_t start_pos,
void **key_name,
size_t *key_len,
void **value,
size_t *value_len);
int (*object_track_start) (
hdb_handle_t object_handle,
object_track_depth_t depth,
object_key_change_notify_fn_t key_change_notify_fn,
object_create_notify_fn_t object_create_notify_fn,
object_destroy_notify_fn_t object_destroy_notify_fn,
object_reload_notify_fn_t object_reload_notify_fn,
void * priv_data_pt);
void (*object_track_stop) (
object_key_change_notify_fn_t key_change_notify_fn,
object_create_notify_fn_t object_create_notify_fn,
object_destroy_notify_fn_t object_destroy_notify_fn,
object_reload_notify_fn_t object_reload_notify_fn,
void * priv_data_pt);
int (*object_write_config) (const char **error_string);
int (*object_reload_config) (
int flush,
const char **error_string);
int (*object_key_increment) (
hdb_handle_t object_handle,
const void *key_name,
size_t key_len,
unsigned int *value);
int (*object_key_decrement) (
hdb_handle_t object_handle,
const void *key_name,
size_t key_len,
unsigned int *value);
};
#endif /* OBJDB_H_DEFINED */
diff --git a/include/corosync/hdb.h b/include/corosync/hdb.h
index 8d8e2cc0..25a6d8b9 100644
--- a/include/corosync/hdb.h
+++ b/include/corosync/hdb.h
@@ -1,344 +1,344 @@
/*
* Copyright (c) 2002-2006 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HDB_H_DEFINED
#define HDB_H_DEFINED
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
typedef unsigned long long hdb_handle_t;
enum HDB_HANDLE_STATE {
HDB_HANDLE_STATE_EMPTY,
HDB_HANDLE_STATE_PENDINGREMOVAL,
HDB_HANDLE_STATE_ACTIVE
};
struct hdb_handle {
int state;
void *instance;
int check;
int ref_count;
};
struct hdb_handle_database {
unsigned int handle_count;
struct hdb_handle *handles;
unsigned int iterator;
#if defined(HAVE_PTHREAD_SPIN_LOCK)
pthread_spinlock_t lock;
#else
pthread_mutex_t lock;
#endif
unsigned int first_run;
};
#if defined(HAVE_PTHREAD_SPIN_LOCK)
static inline void hdb_database_lock (pthread_spinlock_t *spinlock)
{
pthread_spin_lock (spinlock);
}
static inline void hdb_database_unlock (pthread_spinlock_t *spinlock)
{
pthread_spin_unlock (spinlock);
}
static inline void hdb_database_lock_init (pthread_spinlock_t *spinlock)
{
pthread_spin_init (spinlock, 0);
}
static inline void hdb_database_lock_destroy (pthread_spinlock_t *spinlock)
{
pthread_spin_destroy (spinlock);
}
#else
static inline void hdb_database_lock (pthread_mutex_t *mutex)
{
pthread_mutex_lock (mutex);
}
static inline void hdb_database_unlock (pthread_mutex_t *mutex)
{
pthread_mutex_unlock (mutex);
}
static inline void hdb_database_lock_init (pthread_mutex_t *mutex)
{
pthread_mutex_init (mutex, NULL);
}
static inline void hdb_database_lock_destroy (pthread_mutex_t *mutex)
{
pthread_mutex_destroy (mutex);
}
#endif
#define DECLARE_HDB_DATABASE(database_name) \
static struct hdb_handle_database (database_name); \
static void database_name##_init(void)__attribute__((constructor)); \
static void database_name##_init(void) \
{ \
memset (&(database_name), 0, sizeof (struct hdb_handle_database));\
hdb_database_lock_init (&(database_name).lock); \
}
#define DECLARE_HDB_DATABASE_FIRSTRUN(database_name) \
static struct hdb_handle_database (database_name) = { \
.first_run = 1, \
}; \
static void database_name##_init(void)__attribute__((constructor)); \
static void database_name##_init(void) \
{ \
memset (&(database_name), 0, sizeof (struct hdb_handle_database));\
hdb_database_lock_init (&(database_name).lock); \
}
static inline void hdb_create (
struct hdb_handle_database *handle_database)
{
memset (handle_database, 0, sizeof (struct hdb_handle_database));
hdb_database_lock_init (&handle_database->lock);
}
static inline void hdb_destroy (
struct hdb_handle_database *handle_database)
{
free (handle_database->handles);
hdb_database_lock_destroy (&handle_database->lock);
memset (handle_database, 0, sizeof (struct hdb_handle_database));
}
static inline int hdb_handle_create (
struct hdb_handle_database *handle_database,
int instance_size,
hdb_handle_t *handle_id_out)
{
int handle;
unsigned int check;
void *new_handles;
int found = 0;
void *instance;
int i;
if (handle_database->first_run == 1) {
memset (handle_database, 0, sizeof (struct hdb_handle_database));
hdb_database_lock_init (&handle_database->lock);
}
hdb_database_lock (&handle_database->lock);
for (handle = 0; handle < handle_database->handle_count; handle++) {
if (handle_database->handles[handle].state == HDB_HANDLE_STATE_EMPTY) {
found = 1;
break;
}
}
if (found == 0) {
handle_database->handle_count += 1;
new_handles = (struct hdb_handle *)realloc (handle_database->handles,
sizeof (struct hdb_handle) * handle_database->handle_count);
if (new_handles == NULL) {
hdb_database_unlock (&handle_database->lock);
return (-1);
}
handle_database->handles = new_handles;
}
instance = (void *)malloc (instance_size);
if (instance == 0) {
return (-1);
}
/*
* This code makes sure the random number isn't zero
* We use 0 to specify an invalid handle out of the 1^64 address space
* If we get 0 200 times in a row, the RNG may be broken
*/
for (i = 0; i < 200; i++) {
check = random();
if (check != 0 && check != 0xffffffff) {
break;
}
}
memset (instance, 0, instance_size);
handle_database->handles[handle].state = HDB_HANDLE_STATE_ACTIVE;
handle_database->handles[handle].instance = instance;
handle_database->handles[handle].ref_count = 1;
handle_database->handles[handle].check = check;
*handle_id_out = (((unsigned long long)(check)) << 32) | handle;
hdb_database_unlock (&handle_database->lock);
return (0);
}
static inline int hdb_handle_get (
struct hdb_handle_database *handle_database,
hdb_handle_t handle_in,
void **instance)
{
unsigned int check = ((unsigned int)(((unsigned long long)handle_in) >> 32));
unsigned int handle = handle_in & 0xffffffff;
hdb_database_lock (&handle_database->lock);
if (check != 0xffffffff &&
check != handle_database->handles[handle].check) {
hdb_database_unlock (&handle_database->lock);
return (-1);
}
*instance = NULL;
if (handle >= handle_database->handle_count) {
hdb_database_unlock (&handle_database->lock);
return (-1);
}
if (handle_database->handles[handle].state != HDB_HANDLE_STATE_ACTIVE) {
hdb_database_unlock (&handle_database->lock);
return (-1);
}
*instance = handle_database->handles[handle].instance;
handle_database->handles[handle].ref_count += 1;
hdb_database_unlock (&handle_database->lock);
return (0);
}
static inline int hdb_handle_put (
struct hdb_handle_database *handle_database,
hdb_handle_t handle_in)
{
unsigned int check = ((unsigned int)(((unsigned long long)handle_in) >> 32));
unsigned int handle = handle_in & 0xffffffff;
hdb_database_lock (&handle_database->lock);
if (check != 0xffffffff &&
check != handle_database->handles[handle].check) {
hdb_database_unlock (&handle_database->lock);
return (-1);
}
-
+
handle_database->handles[handle].ref_count -= 1;
assert (handle_database->handles[handle].ref_count >= 0);
if (handle_database->handles[handle].ref_count == 0) {
free (handle_database->handles[handle].instance);
memset (&handle_database->handles[handle], 0, sizeof (struct hdb_handle));
}
hdb_database_unlock (&handle_database->lock);
return (0);
}
static inline int hdb_handle_destroy (
struct hdb_handle_database *handle_database,
hdb_handle_t handle_in)
{
unsigned int check = ((unsigned int)(((unsigned long long)handle_in) >> 32));
unsigned int handle = handle_in & 0xffffffff;
int res;
hdb_database_lock (&handle_database->lock);
if (check != 0xffffffff &&
check != handle_database->handles[handle].check) {
hdb_database_unlock (&handle_database->lock);
return (-1);
}
handle_database->handles[handle].state = HDB_HANDLE_STATE_PENDINGREMOVAL;
hdb_database_unlock (&handle_database->lock);
res = hdb_handle_put (handle_database, handle);
return (res);
}
static inline void hdb_iterator_reset (
struct hdb_handle_database *handle_database)
{
handle_database->iterator = 0;
}
static inline int hdb_iterator_next (
struct hdb_handle_database *handle_database,
void **instance,
hdb_handle_t *handle)
{
int res = -1;
while (handle_database->iterator < handle_database->handle_count) {
*handle = ((unsigned long long)(handle_database->handles[handle_database->iterator].check) << 32) | handle_database->iterator;
res = hdb_handle_get (
handle_database,
*handle,
instance);
handle_database->iterator += 1;
if (res == 0) {
break;
}
}
return (res);
}
static inline unsigned int hdb_base_convert (hdb_handle_t handle)
{
return (handle & 0xffffffff);
}
static inline unsigned long long hdb_nocheck_convert (unsigned int handle)
{
unsigned long long retvalue = 0xffffffffULL << 32 | handle;
return (retvalue);
}
#endif /* HDB_H_DEFINED */
diff --git a/include/corosync/ipc_cfg.h b/include/corosync/ipc_cfg.h
index a01bab35..9b6424d6 100644
--- a/include/corosync/ipc_cfg.h
+++ b/include/corosync/ipc_cfg.h
@@ -1,229 +1,229 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AIS_IPC_CFG_H_DEFINED
#define AIS_IPC_CFG_H_DEFINED
#include <netinet/in.h>
#include <corosync/corotypes.h>
#include "ipc_gen.h"
#include "cfg.h"
enum req_lib_cfg_types {
MESSAGE_REQ_CFG_RINGSTATUSGET = 0,
MESSAGE_REQ_CFG_RINGREENABLE = 1,
MESSAGE_REQ_CFG_STATETRACKSTART = 2,
MESSAGE_REQ_CFG_STATETRACKSTOP = 3,
MESSAGE_REQ_CFG_ADMINISTRATIVESTATESET = 4,
MESSAGE_REQ_CFG_ADMINISTRATIVESTATEGET = 5,
MESSAGE_REQ_CFG_SERVICELOAD = 6,
MESSAGE_REQ_CFG_SERVICEUNLOAD = 7,
MESSAGE_REQ_CFG_KILLNODE = 8,
MESSAGE_REQ_CFG_TRYSHUTDOWN = 9,
MESSAGE_REQ_CFG_REPLYTOSHUTDOWN = 10,
MESSAGE_REQ_CFG_GET_NODE_ADDRS = 11,
MESSAGE_REQ_CFG_LOCAL_GET = 12
};
enum res_lib_cfg_types {
MESSAGE_RES_CFG_RINGSTATUSGET = 0,
MESSAGE_RES_CFG_RINGREENABLE = 1,
MESSAGE_RES_CFG_STATETRACKSTART = 2,
MESSAGE_RES_CFG_STATETRACKSTOP = 3,
MESSAGE_RES_CFG_ADMINISTRATIVESTATESET = 4,
MESSAGE_RES_CFG_ADMINISTRATIVESTATEGET = 5,
MESSAGE_RES_CFG_SERVICELOAD = 6,
MESSAGE_RES_CFG_SERVICEUNLOAD = 7,
MESSAGE_RES_CFG_KILLNODE = 8,
MESSAGE_RES_CFG_TRYSHUTDOWN = 9,
MESSAGE_RES_CFG_TESTSHUTDOWN = 10,
MESSAGE_RES_CFG_GET_NODE_ADDRS = 11,
MESSAGE_RES_CFG_LOCAL_GET = 12,
MESSAGE_RES_CFG_REPLYTOSHUTDOWN = 13
};
struct req_lib_cfg_statetrack {
mar_req_header_t header;
uint8_t track_flags;
corosync_cfg_state_notification_t *notification_buffer_address;
};
struct res_lib_cfg_statetrack {
mar_res_header_t header;
};
struct req_lib_cfg_statetrackstop {
mar_req_header_t header;
};
struct res_lib_cfg_statetrackstop {
mar_res_header_t header;
};
struct req_lib_cfg_administrativestateset {
mar_req_header_t header;
cs_name_t comp_name;
corosync_cfg_administrative_target_t administrative_target;
corosync_cfg_administrative_state_t administrative_state;
};
struct res_lib_cfg_administrativestateset {
mar_res_header_t header;
};
struct req_lib_cfg_administrativestateget {
mar_req_header_t header;
cs_name_t comp_name;
corosync_cfg_administrative_target_t administrative_target;
corosync_cfg_administrative_state_t administrative_state;
};
struct res_lib_cfg_administrativestateget {
mar_res_header_t header __attribute__((aligned(8)));
};
struct req_lib_cfg_ringstatusget {
mar_req_header_t header __attribute__((aligned(8)));
};
struct res_lib_cfg_ringstatusget {
mar_res_header_t header __attribute__((aligned(8)));
mar_uint32_t interface_count __attribute__((aligned(8)));
char interface_name[16][128] __attribute__((aligned(8)));
char interface_status[16][512] __attribute__((aligned(8)));
};
struct req_lib_cfg_ringreenable {
mar_req_header_t header __attribute__((aligned(8)));
};
struct res_lib_cfg_ringreenable {
mar_res_header_t header __attribute__((aligned(8)));
};
struct req_lib_cfg_serviceload {
mar_res_header_t header __attribute__((aligned(8)));
char service_name[256] __attribute__((aligned(8)));
unsigned int service_ver;
};
struct res_lib_cfg_serviceload {
mar_res_header_t header __attribute__((aligned(8)));
};
struct req_lib_cfg_serviceunload {
mar_res_header_t header __attribute__((aligned(8)));
char service_name[256] __attribute__((aligned(8)));
unsigned int service_ver;
};
struct res_lib_cfg_serviceunload {
mar_res_header_t header __attribute__((aligned(8)));
};
struct req_lib_cfg_killnode {
mar_req_header_t header __attribute__((aligned(8)));
unsigned int nodeid __attribute__((aligned(8)));
cs_name_t reason __attribute__((aligned(8)));
};
struct res_lib_cfg_killnode {
mar_res_header_t header __attribute__((aligned(8)));
};
struct req_lib_cfg_tryshutdown {
mar_req_header_t header __attribute__((aligned(8)));
unsigned int flags;
};
struct res_lib_cfg_tryshutdown {
mar_res_header_t header __attribute__((aligned(8)));
};
struct req_lib_cfg_replytoshutdown {
mar_req_header_t header __attribute__((aligned(8)));
unsigned int response;
};
struct res_lib_cfg_replytoshutdown {
mar_res_header_t header __attribute__((aligned(8)));
};
struct res_lib_cfg_testshutdown {
mar_res_header_t header __attribute__((aligned(8)));
unsigned int flags;
};
struct req_lib_cfg_get_node_addrs {
mar_req_header_t header __attribute__((aligned(8)));
unsigned int nodeid;
};
struct res_lib_cfg_get_node_addrs {
mar_res_header_t header __attribute__((aligned(8)));
unsigned int family;
unsigned int num_addrs;
char addrs[TOTEMIP_ADDRLEN][0];
};
struct req_lib_cfg_local_get {
mar_req_header_t header __attribute__((aligned(8)));
};
struct res_lib_cfg_local_get {
mar_res_header_t header __attribute__((aligned(8)));
mar_uint32_t local_nodeid __attribute__((aligned(8)));
};
typedef enum {
AIS_AMF_ADMINISTRATIVETARGET_SERVICEUNIT = 0,
AIS_AMF_ADMINISTRATIVETARGET_SERVICEGROUP = 1,
AIS_AMF_ADMINISTRATIVETARGET_COMPONENTSERVICEINSTANCE = 2,
AIS_AMF_ADMINISTRATIVETARGET_NODE = 3
} corosync_administrative_target_t;
typedef enum {
AIS_AMF_ADMINISTRATIVESTATE_UNLOCKED = 0,
AIS_AMF_ADMINISTRATIVESTATE_LOCKED = 1,
AIS_AMF_ADMINISTRATIVESTATE_STOPPING = 2
} corosync_administrative_state_t;
typedef enum {
CFG_SHUTDOWN_FLAG_REQUEST = 0,
CFG_SHUTDOWN_FLAG_REGARDLESS = 1,
CFG_SHUTDOWN_FLAG_IMMEDIATE = 2,
} corosync_shutdown_flags_t;
#endif /* AIS_IPC_CFG_H_DEFINED */
diff --git a/include/corosync/ipc_evs.h b/include/corosync/ipc_evs.h
index 5f20a6e8..3eb53396 100644
--- a/include/corosync/ipc_evs.h
+++ b/include/corosync/ipc_evs.h
@@ -1,138 +1,138 @@
/*
* Copyright (c) 2002-2004 MontaVista Software, 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.
*/
#ifndef IPC_EVS_H_DEFINED
#define IPC_EVS_H_DEFINED
#include <corosync/corotypes.h>
#include "evs.h"
#include "ipc_gen.h"
enum req_lib_evs_types {
MESSAGE_REQ_EVS_JOIN = 0,
MESSAGE_REQ_EVS_LEAVE = 1,
MESSAGE_REQ_EVS_MCAST_JOINED = 2,
MESSAGE_REQ_EVS_MCAST_GROUPS = 3,
MESSAGE_REQ_EVS_MEMBERSHIP_GET = 4
};
enum res_lib_evs_types {
MESSAGE_RES_EVS_DELIVER_CALLBACK = 0,
MESSAGE_RES_EVS_CONFCHG_CALLBACK = 1,
MESSAGE_RES_EVS_JOIN = 2,
MESSAGE_RES_EVS_LEAVE = 3,
MESSAGE_RES_EVS_MCAST_JOINED = 4,
MESSAGE_RES_EVS_MCAST_GROUPS = 5,
MESSAGE_RES_EVS_MEMBERSHIP_GET = 6
};
struct res_evs_deliver_callback {
mar_res_header_t header;
unsigned int local_nodeid;
size_t msglen;
char msg[0];
};
struct res_evs_confchg_callback {
mar_res_header_t header;
size_t member_list_entries;
size_t left_list_entries;
size_t joined_list_entries;
unsigned int member_list[PROCESSOR_COUNT_MAX];
unsigned int left_list[PROCESSOR_COUNT_MAX];
unsigned int joined_list[PROCESSOR_COUNT_MAX];
};
struct req_lib_evs_join {
mar_res_header_t header;
size_t group_entries;
struct evs_group groups[0];
};
struct res_lib_evs_join {
mar_res_header_t header;
};
struct req_lib_evs_leave {
mar_res_header_t header;
size_t group_entries;
struct evs_group groups[0];
};
struct res_lib_evs_leave {
mar_res_header_t header;
};
struct req_lib_evs_mcast_joined {
mar_res_header_t header;
evs_guarantee_t guarantee;
size_t msg_len;
char msg[0];
};
struct res_lib_evs_mcast_joined {
mar_res_header_t header;
};
struct req_lib_evs_mcast_groups {
mar_res_header_t header;
evs_guarantee_t guarantee;
size_t msg_len;
size_t group_entries;
struct evs_group groups[0];
};
struct res_lib_evs_mcast_groups {
mar_res_header_t header;
};
struct req_exec_evs_mcast {
mar_req_header_t header;
size_t group_entries;
size_t msg_len;
struct evs_group groups[0];
/* data goes here */
};
struct req_lib_evs_membership_get {
mar_req_header_t header;
};
struct res_lib_evs_membership_get {
mar_res_header_t header;
unsigned int local_nodeid;
unsigned int member_list[PROCESSOR_COUNT_MAX];
size_t member_list_entries;
};
#endif /* IPC_EVS_H_DEFINED */
diff --git a/include/corosync/ipc_gen.h b/include/corosync/ipc_gen.h
index 7ec9eaae..0db936c5 100644
--- a/include/corosync/ipc_gen.h
+++ b/include/corosync/ipc_gen.h
@@ -1,169 +1,169 @@
/*
* Copyright (c) 2002-2005 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IPC_GEN_H_DEFINED
#define IPC_GEN_H_DEFINED
#include <corosync/mar_gen.h>
enum service_types {
EVS_SERVICE = 0,
CLM_SERVICE = 1,
AMF_SERVICE = 2,
CKPT_SERVICE = 3,
EVT_SERVICE = 4,
LCK_SERVICE = 5,
MSG_SERVICE = 6,
CFG_SERVICE = 7,
CPG_SERVICE = 8,
CONFDB_SERVICE = 10,
QUORUM_SERVICE = 11,
PLOAD_SERVICE = 12,
TMR_SERVICE = 13,
VOTEQUORUM_SERVICE = 14,
};
#define IPC_SOCKET_NAME "corosync.ipc"
enum req_init_types {
MESSAGE_REQ_RESPONSE_INIT = 0,
MESSAGE_REQ_DISPATCH_INIT = 1
};
#define MESSAGE_REQ_CHANGE_EUID 1
#define MESSAGE_REQ_OUTQ_FLUSH 2
#define IPC_REQUEST_SIZE 8192*128
#define IPC_RESPONSE_SIZE 8192*128
#define IPC_DISPATCH_SIZE 8192*128
struct control_buffer {
unsigned int read;
unsigned int write;
};
enum res_init_types {
MESSAGE_RES_INIT
};
typedef struct {
int size __attribute__((aligned(8)));
int id __attribute__((aligned(8)));
} mar_req_header_t __attribute__((aligned(8)));
typedef struct {
int service __attribute__((aligned(8)));
unsigned long long semkey __attribute__((aligned(8)));
char control_file[64] __attribute__((aligned(8)));
char request_file[64] __attribute__((aligned(8)));
char response_file[64] __attribute__((aligned(8)));
char dispatch_file[64] __attribute__((aligned(8)));
size_t control_size __attribute__((aligned(8)));
size_t request_size __attribute__((aligned(8)));
size_t response_size __attribute__((aligned(8)));
size_t dispatch_size __attribute__((aligned(8)));
} mar_req_setup_t __attribute__((aligned(8)));
typedef struct {
int error __attribute__((aligned(8)));
} mar_res_setup_t __attribute__((aligned(8)));
static inline void swab_mar_req_header_t (mar_req_header_t *to_swab)
{
swab_mar_int32_t (&to_swab->size);
swab_mar_int32_t (&to_swab->id);
}
typedef struct {
- int size; __attribute__((aligned(8)))
+ int size; __attribute__((aligned(8)))
int id __attribute__((aligned(8)));
cs_error_t error __attribute__((aligned(8)));
} mar_res_header_t __attribute__((aligned(8)));
typedef struct {
uid_t euid __attribute__((aligned(8)));
gid_t egid __attribute__((aligned(8)));
} mar_req_priv_change __attribute__((aligned(8)));
typedef struct {
mar_res_header_t header __attribute__((aligned(8)));
mar_uint64_t conn_info __attribute__((aligned(8)));
} mar_res_lib_response_init_t __attribute__((aligned(8)));
typedef struct {
mar_res_header_t header __attribute__((aligned(8)));
} mar_res_lib_dispatch_init_t __attribute__((aligned(8)));
typedef struct {
mar_uint32_t nodeid __attribute__((aligned(8)));
void *conn __attribute__((aligned(8)));
} mar_message_source_t __attribute__((aligned(8)));
typedef struct {
mar_req_header_t header __attribute__((aligned(8)));
size_t map_size __attribute__((aligned(8)));
char path_to_file[128] __attribute__((aligned(8)));
} mar_req_coroipcc_zc_alloc_t __attribute__((aligned(8)));
typedef struct {
mar_req_header_t header __attribute__((aligned(8)));
size_t map_size __attribute__((aligned(8)));
uint64_t server_address __attribute__((aligned(8)));
} mar_req_coroipcc_zc_free_t __attribute__((aligned(8)));
typedef struct {
mar_req_header_t header __attribute__((aligned(8)));
uint64_t server_address __attribute__((aligned(8)));
} mar_req_coroipcc_zc_execute_t __attribute__((aligned(8)));
struct coroipcs_zc_header {
int map_size;
uint64_t server_address;
};
static inline void swab_mar_message_source_t (mar_message_source_t *to_swab)
{
swab_mar_uint32_t (&to_swab->nodeid);
/*
* if it is from a byteswapped machine, then we can safely
* ignore its conn info data structure since this is only
* local to the machine
*/
to_swab->conn = NULL;
}
#define ZC_ALLOC_HEADER 0xFFFFFFFF
#define ZC_FREE_HEADER 0xFFFFFFFE
#define ZC_EXECUTE_HEADER 0xFFFFFFFD
#endif /* IPC_GEN_H_DEFINED */
diff --git a/include/corosync/ipc_pload.h b/include/corosync/ipc_pload.h
index fdc3c44b..48057dae 100644
--- a/include/corosync/ipc_pload.h
+++ b/include/corosync/ipc_pload.h
@@ -1,71 +1,71 @@
/*
* 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.
*/
#ifndef IPC_PLOAD_H_DEFINED
#define IPC_PLOAD_H_DEFINED
#include <corosync/corotypes.h>
#include "pload.h"
#include "ipc_gen.h"
enum req_lib_evs_types {
MESSAGE_REQ_PLOAD_START = 0,
};
enum res_lib_evs_types {
MESSAGE_RES_PLOAD_START = 0,
};
struct res_lib_pload_start {
mar_res_header_t header;
unsigned int dataset[1024];
};
struct res_lib_pload_mcast {
mar_res_header_t header;
};
struct req_lib_pload_start {
mar_req_header_t header;
unsigned int msg_code;
unsigned int msg_size;
unsigned int msg_count;
unsigned int time_interval;
};
struct req_lib_pload_mcast {
mar_req_header_t header;
unsigned int code;
};
#endif /* IPC_PLOAD_H_DEFINED */
diff --git a/include/corosync/lcr/lcr_ifact.h b/include/corosync/lcr/lcr_ifact.h
index 9124b2ba..4ae59c6e 100644
--- a/include/corosync/lcr/lcr_ifact.h
+++ b/include/corosync/lcr/lcr_ifact.h
@@ -1,46 +1,46 @@
/*
* Copyright (C) 2006 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.
*/
#ifndef LCR_IFACT_H_DEFINED
#define LCR_IFACT_H_DEFINED
#include <corosync/hdb.h>
int lcr_ifact_reference (
hdb_handle_t *handle,
const char *iface_name,
int version,
void **interface,
void *context);
int lcr_ifact_release (
hdb_handle_t handle);
#endif /* LCR_IFACT_H_DEFINED */
diff --git a/include/corosync/pload.h b/include/corosync/pload.h
index 78de5e09..3e34b54a 100644
--- a/include/corosync/pload.h
+++ b/include/corosync/pload.h
@@ -1,100 +1,100 @@
/*
* 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.
*/
#ifndef COROSYNC_PLOAD_H_DEFINED
#define COROSYNC_PLOAD_H_DEFINED
#include <sys/types.h>
#include <netinet/in.h>
/**
* @defgroup corosync Other API services provided by corosync
*/
/**
* @addtogroup pload_corosync
*
* @{
*/
typedef uint64_t pload_handle_t;
typedef enum {
PLOAD_OK = 1,
PLOAD_ERR_LIBRARY = 2,
PLOAD_ERR_TIMEOUT = 5,
PLOAD_ERR_TRY_AGAIN = 6,
PLOAD_ERR_INVALID_PARAM = 7,
PLOAD_ERR_NO_MEMORY = 8,
PLOAD_ERR_BAD_HANDLE = 9,
PLOAD_ERR_ACCESS = 11,
PLOAD_ERR_NOT_EXIST = 12,
PLOAD_ERR_EXIST = 14,
PLOAD_ERR_NOT_SUPPORTED = 20,
PLOAD_ERR_SECURITY = 29,
PLOAD_ERR_TOO_MANY_GROUPS=30
} pload_error_t;
typedef struct {
int callback;
} pload_callbacks_t;
/** @} */
/*
* Create a new pload connection
*/
pload_error_t pload_initialize (
pload_handle_t *handle,
pload_callbacks_t *callbacks);
/*
* Close the pload handle
*/
pload_error_t pload_finalize (
pload_handle_t handle);
/*
* Get a file descriptor on which to poll. pload_handle_t is NOT a
* file descriptor and may not be used directly.
*/
pload_error_t pload_fd_get (
pload_handle_t handle,
int *fd);
unsigned int pload_start (
pload_handle_t handle,
unsigned int code,
unsigned int msg_count,
unsigned int msg_size);
#endif /* COROSYNC_PLOAD_H_DEFINED */
diff --git a/include/corosync/swab.h b/include/corosync/swab.h
index 2da04507..8716d602 100644
--- a/include/corosync/swab.h
+++ b/include/corosync/swab.h
@@ -1,64 +1,64 @@
/*
* Copyright (c) 2005 MontaVista Software, Inc.
* Copyright (c) 2006-2008 Red Hat, Inc.
*
* All rights reserved.
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#define swab16(x) \
({ \
uint16_t __x = (x); \
((uint16_t)( \
(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
})
#define swab32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define swab64(x) \
({ \
uint64_t __x = (x); \
((uint64_t)( \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
diff --git a/include/corosync/totem/coropoll.h b/include/corosync/totem/coropoll.h
index 57edf88a..c095e404 100644
--- a/include/corosync/totem/coropoll.h
+++ b/include/corosync/totem/coropoll.h
@@ -1,93 +1,93 @@
/*
* Copyright (c) 2003-2004 MontaVista Software, 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.
*/
#ifndef POLL_H_DEFINED
#define POLL_H_DEFINED
#include <corosync/hdb.h>
#include <pthread.h>
typedef void * poll_timer_handle;
hdb_handle_t poll_create (void);
int poll_destroy (hdb_handle_t hdb_handle_t);
int poll_dispatch_add (
hdb_handle_t handle,
int fd,
int events,
void *data,
int (*dispatch_fn) (hdb_handle_t handle,
int fd,
int revents,
void *data));
int poll_dispatch_modify (
hdb_handle_t handle,
int fd,
int events,
int (*dispatch_fn) (hdb_handle_t hdb_handle_t,
int fd,
int revents,
void *data));
int poll_dispatch_delete (
hdb_handle_t handle,
int fd);
int poll_timer_add (
hdb_handle_t handle,
int msec_in_future, void *data,
void (*timer_fn) (void *data),
poll_timer_handle *timer_handle_out);
int poll_timer_delete (
hdb_handle_t handle,
poll_timer_handle timer_handle);
int poll_run (
hdb_handle_t handle);
int poll_stop (
hdb_handle_t handle);
#ifdef COMPILE_OUT
void poll_print_state (
hdb_handle_t handle, int fd);
#endif
#endif /* POLL_H_DEFINED */
diff --git a/init/generic b/init/generic
index b63a85c1..f13be6b0 100755
--- a/init/generic
+++ b/init/generic
@@ -1,145 +1,145 @@
#!/bin/sh
#
# corosync Start the Corosync Cluster Engine
#
# Author: Andrew Beekhof <abeekhof@suse.de>
# License: Revised BSD
#
# chkconfig: - 20 20
# processname: corosync
# description: Corosync Cluster Engine
#
### BEGIN INIT INFO
# Description: corosync....
#
# Short-Description: Corosync Cluster Engine.
# Provides: corosync
# Required-Start: $network
# Should-Start: $syslog
# Required-Stop: $network
# Default-Start: 3 5
# Default-Stop: 0 6
### END INIT INFO
do_force=0
prog="corosync"
lockfile="/var/lock/subsys/$prog"
internal_status() {
killall -0 corosync > /dev/null 2>&1
return $?
}
status() {
- if
+ if
! internal_status
then
echo "Stopped"
return 7
fi
echo "Running"
return 0
}
start() {
echo -n $"Starting Corosync Cluster Engine ($prog): "
- if
+ if
! internal_status
then
echo -n "starting... "
$prog 2>&1 > /dev/null 2>&1
echo -n "rc=$?: "
fi
sleep 2 # give it time to fail... $? isn't definitive
- if
+ if
internal_status
then
echo "OK"
return 0
fi
echo "Failed"
return 1
}
do_force=0
do_forever=1
stop() {
echo -n $"Stopping Corosync Cluster Engine ($prog): "
killall -QUIT corosync
if [ $do_forever = 0 ]; then
for i in 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20; do
if
internal_status
then
sleep 2
echo -n "."
else
rm -f "$lockfile"
echo "OK"
return 0
fi
done
if [ $do_force = 1 ]; then
echo -n "Escalating... "
killall -KILL corosync
sleep 5
-
+
if
! internal_status
then
rm -f "$lockfile"
echo "OK"
return 0
fi
fi
echo "Failed"
return 1
fi
- while
+ while
internal_status
do
sleep 1
echo -n "."
done
-
+
rm -f "$lockfile"
echo "OK"
return 0
}
restart() {
stop
start
}
case "$1" in
start|stop|restart)
$1
;;
force-stop)
do_force=1
stop
;;
reload|force-reload)
restart
;;
condrestart|try-restart)
[ ! -f "$lockfile" ] || restart
;;
status)
status $prog
;;
*)
echo $"Usage: $0 {start|stop|restart|try-restart|condrestart|reload|force-reload|force-stop|status}"
exit 2
esac
diff --git a/init/mvlcge b/init/mvlcge
index 059720a2..1d68ba76 100755
--- a/init/mvlcge
+++ b/init/mvlcge
@@ -1,28 +1,28 @@
#! /bin/sh
#
-# Application Interface Specification Startup
+# Application Interface Specification Startup
# chkconfig: 2345 20 20
PATH=/bin:/usr/bin:/sbin:/usr/sbin
test -f /usr/sbin/corosync | exit 0
-case "$1" in
+case "$1" in
start)
- echo -n "Starting Corosync Cluster Engine: "
+ echo -n "Starting Corosync Cluster Engine: "
start-stop-daemon --start --quiet --exec /usr/sbin/corosync
echo "."
;;
stop)
- echo -n "Stopping Corosync Cluster Engine: "
+ echo -n "Stopping Corosync Cluster Engine: "
start-stop-daemon --stop --quiet --exec /usr/sbin/corosync
echo "."
;;
*)
echo "Usage: /etc/init.d/corosync {start|stop}" >&2
exit 1
;;
esac
diff --git a/lcr/Makefile.am b/lcr/Makefile.am
index 7dda46de..deb85a54 100644
--- a/lcr/Makefile.am
+++ b/lcr/Makefile.am
@@ -1,69 +1,69 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
AM_CFLAGS = -fPIC
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
lib_LIBRARIES = liblcr.a
noinst_PROGRAMS = test test_static uic
noinst_LCRSO = libtest_a.lcrso libtest_b.lcrso
uic_SOURCES = uic.c
liblcr_a_SOURCES = lcr_ifact.c
test_SOURCES = test.c uis.c
test_LDADD = liblcr.a
test_static_SOURCES = test.c libtest_a.c libtest_b.c uis.c lcr_ifact.c
if BUILD_DARWIN
%.lcrso: %.o
$(CC) $(CFLAGS) -bundle -bundle_loader ./test $^ -o $@
else
%.lcrso: %.o
$(CC) $(CFLAGS) -shared -Wl,-soname,$@ $^ -o $@
endif
lint:
-splint $(LINT_FLAGS) $(CFLAGS) *.c
all-local: $(noinst_LCRSO)
@echo Built Live Component Replacement System
clean-local:
rm -f *.o *.a *.so* *.da *.bb *.bbg *.lcrso
diff --git a/lcr/README.lcr b/lcr/README.lcr
index 95820691..ad782d05 100644
--- a/lcr/README.lcr
+++ b/lcr/README.lcr
@@ -1,113 +1,113 @@
Live Component Replacement
--------------------------
All software is composed of components, which contain multiple software classes.
Components generally depend upon other components and sometimes classes from
other components.
Some components of corosync are the evt service, the ckpt service, the clm
service, the totem protocol, and others. If a defect is found in any of
these components, the entire ais executive must be stopped, replaced, and
restarted.
The lcr code formalizes the concept of components into dynamic libraries. A
component may have multiple classes. Each class (the lcr code uses the word
interface) may have multiple functions within the class. Each interface may
depend upon other interfaces, and those interfaces are then loaded prior to the
requested interface being referenced.
Note that with recent changes, the lcr interface factory can be used when
statically linking without additional steps. The interface for notifying
lcr of a component has changed.
A list of shared objects is scanned each time an interface is requested to
load via the following interface:
int lcr_ifact_reference (
void **handle,
char *iface_name,
int version,
void **interface,
void *context);
-The iface_name is the name of the interface, the version is the version,
+The iface_name is the name of the interface, the version is the version,
the void **interface is the list of functions returned once the interface
has been dynamically loaded and referenced, and context is passed to the
constructor and destructor.
The interface is loaded, the interface constructor is called, and the list
of interfaces is returned back to the caller.
First the list of interfaces is described in an iface_list data structure:
struct iface_list iface_list = {
.iface1_func1 = iface1_func1,
.iface1_func2 = iface1_func2,
.iface1_func3 = iface1_func3,
};
iface1_func1 is a simple function call.
Then the lcr_iface data structure is defined for the c file:
struct lcr_iface iface1_ver0 = {
.name = "iface1",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = iface1_constructor,
.destructor = iface1_destructor,
.interfaces = (void **)&iface_list,
};
The name and version fields provide naming and versioning. The constructor
and destructor functions execute at reference and release times. Finally
the .interfaces type describes the list of functions used for the interface.
Next, an lcr_comp must be described:
struct lcr_comp test_comp = {
.iface_count = 2,
.ifaces = lcr_ifaces
};
the iface count describes the number of interfaces within the component,
and lcr_ifaces is an array of pointers to lcr_iface data types.
The lcr_comp_get method has been replaced. The final step is to setup a
constructor that is started when the task is started. This ctor will
register the component with the lcr framework.
static void register_this_component (void) {
lcr_component_register (&test_comp);
}
static void (*const __init_this_component[1]) (void) __attribute__ ((section(".ctors"))) = { register_this_component };
Now the component can be referenced and used in another application.
int main ()
{
.....
lcr_ifact_reference (
&ifact_handle_ver0,
"iface1",
0, /* version 0 */
(void **)&iface_ver0,
(void *)0xdeadbeef);
iface_ver0->func1();
iface_ver0->func2();
iface_ver0->func3();
}
See libtest_a and libtest_b for two sample components. The test program
demonstrates usage. The test_static demonstrates operation when statically
linked. Note the dynamic inteface factory is still available for use when
statically linking components.
-On startup, a thread is created which listens for requests from the "uic"
+On startup, a thread is created which listens for requests from the "uic"
application. These requests are then processed by the lcr service which
would execute a live replacement.
diff --git a/lcr/lcr_ifact.c b/lcr/lcr_ifact.c
index ce56de70..bb087d78 100644
--- a/lcr/lcr_ifact.c
+++ b/lcr/lcr_ifact.c
@@ -1,545 +1,545 @@
/*
* Copyright (C) 2006 Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <dlfcn.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fnmatch.h>
#ifdef COROSYNC_SOLARIS
#include <iso/limits_iso.h>
#endif
#include <corosync/hdb.h>
#include <corosync/lcr/lcr_comp.h>
#include <corosync/lcr/lcr_ifact.h>
#include <corosync/hdb.h>
#include <stdlib.h>
struct lcr_component_instance {
struct lcr_iface *ifaces;
int iface_count;
hdb_handle_t comp_handle;
void *dl_handle;
int refcount;
char library_name[256];
};
struct lcr_iface_instance {
hdb_handle_t component_handle;
void *context;
void (*destructor) (void *context);
};
-
+
DECLARE_HDB_DATABASE_FIRSTRUN (lcr_component_instance_database);
DECLARE_HDB_DATABASE_FIRSTRUN (lcr_iface_instance_database);
/*
static struct hdb_handle_database lcr_component_instance_database = {
.handle_count = 0,
.handles = 0,
.iterator = 0
};
static struct hdb_handle_database lcr_iface_instance_database = {
.handle_count = 0,
.handles = 0,
.iterator = 0
};
*/
static hdb_handle_t g_component_handle = 0xFFFFFFFF;
#if defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS)
static int lcr_select_so (const struct dirent *dirent)
#else
static int lcr_select_so (struct dirent *dirent)
#endif
{
unsigned int len;
len = strlen (dirent->d_name);
if (len > 6) {
if (strcmp (".lcrso", dirent->d_name + len - 6) == 0) {
return (1);
}
}
return (0);
}
#ifndef COROSYNC_SOLARIS
#ifdef COROSYNC_LINUX
static int pathlist_select (const struct dirent *dirent)
#else
static int pathlist_select (struct dirent *dirent)
#endif
{
if (fnmatch ("*.conf", dirent->d_name, 0) == 0) {
return (1);
}
return (0);
}
#endif
static inline struct lcr_component_instance *lcr_comp_find (
const char *iface_name,
unsigned int version,
unsigned int *iface_number)
{
struct lcr_component_instance *instance;
void *instance_p = NULL;
hdb_handle_t component_handle = 0;
int i;
/*
* Try to find interface in already loaded component
*/
hdb_iterator_reset (&lcr_component_instance_database);
while (hdb_iterator_next (&lcr_component_instance_database,
&instance_p, &component_handle) == 0) {
instance = (struct lcr_component_instance *)instance_p;
for (i = 0; i < instance->iface_count; i++) {
if ((strcmp (instance->ifaces[i].name, iface_name) == 0) &&
instance->ifaces[i].version == version) {
*iface_number = i;
return (instance);
}
}
hdb_handle_put (&lcr_component_instance_database, component_handle);
}
return (NULL);
}
static inline int lcr_lib_loaded (
char *library_name)
{
struct lcr_component_instance *instance;
void *instance_p = NULL;
hdb_handle_t component_handle = 0;
/*
* Try to find interface in already loaded component
*/
hdb_iterator_reset (&lcr_component_instance_database);
while (hdb_iterator_next (&lcr_component_instance_database,
(void *)&instance_p, &component_handle) == 0) {
instance = (struct lcr_component_instance *)instance_p;
if (strcmp (instance->library_name, library_name) == 0) {
return (1);
}
hdb_handle_put (&lcr_component_instance_database, component_handle);
}
return (0);
}
enum { PATH_LIST_SIZE = 128 };
const char *path_list[PATH_LIST_SIZE];
unsigned int path_list_entries = 0;
static void defaults_path_build (void)
{
char cwd[1024];
char *res;
res = getcwd (cwd, sizeof (cwd));
if (res != NULL && (path_list[0] = strdup (cwd)) != NULL) {
path_list_entries++;
}
-
+
path_list[path_list_entries++] = LCRSODIR;
}
static void ld_library_path_build (void)
{
char *ld_library_path;
char *my_ld_library_path;
char *p_s, *ptrptr;
ld_library_path = getenv ("LD_LIBRARY_PATH");
if (ld_library_path == NULL) {
return;
}
my_ld_library_path = strdup (ld_library_path);
if (my_ld_library_path == NULL) {
return;
}
p_s = strtok_r (my_ld_library_path, ":", &ptrptr);
while (p_s != NULL) {
char *p = strdup (p_s);
if (p && path_list_entries < PATH_LIST_SIZE) {
path_list[path_list_entries++] = p;
}
p_s = strtok_r (NULL, ":", &ptrptr);
}
free (my_ld_library_path);
}
static int ldso_path_build (const char *path, const char *filename)
{
#ifndef COROSYNC_SOLARIS
FILE *fp;
char string[1024];
char filename_cat[1024];
char newpath[1024];
char *newpath_tmp;
char *new_filename;
int j;
struct dirent **scandir_list;
unsigned int scandir_entries;
snprintf (filename_cat, sizeof(filename_cat), "%s/%s", path, filename);
if (filename[0] == '*') {
scandir_entries = scandir (
path,
&scandir_list,
pathlist_select, alphasort);
if (scandir_entries == 0) {
return 0;
} else if (scandir_entries == -1) {
return -1;
} else {
for (j = 0; j < scandir_entries; j++) {
ldso_path_build (path, scandir_list[j]->d_name);
}
}
}
fp = fopen (filename_cat, "r");
if (fp == NULL) {
return (-1);
}
while (fgets (string, sizeof (string), fp)) {
char *p;
if (strlen(string) > 0)
string[strlen(string) - 1] = '\0';
if (strncmp (string, "include", strlen ("include")) == 0) {
newpath_tmp = string + strlen ("include") + 1;
for (j = strlen (string);
string[j] != ' ' &&
string[j] != '/' &&
j > 0;
j--) {
}
string[j] = '\0';
new_filename = &string[j] + 1;
strcpy (newpath, path);
strcat (newpath, "/");
strcat (newpath, newpath_tmp);
ldso_path_build (newpath, new_filename);
continue;
}
p = strdup (string);
if (p && path_list_entries < PATH_LIST_SIZE) {
path_list[path_list_entries++] = p;
}
}
fclose(fp);
#endif
return (0);
}
#if defined (COROSYNC_SOLARIS) && !defined(HAVE_SCANDIR)
static int scandir (
const char *dir, struct dirent ***namelist,
int (*filter)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **))
{
DIR *d;
struct dirent *entry, **names = NULL;
int namelist_items = 0, namelist_size = 0;
d = opendir(dir);
if (d == NULL)
return -1;
names = NULL;
while ((entry = readdir (d)) != NULL) {
struct dirent *tmpentry;
if ((filter != NULL) && ((*filter)(entry) == 0)) {
continue;
}
if (namelist_items >= namelist_size) {
struct dirent **tmp;
namelist_size += 512;
if ((unsigned long)namelist_size > INT_MAX) {
errno = EOVERFLOW;
goto fail;
}
tmp = realloc (names,
namelist_size * sizeof(struct dirent *));
if (tmp == NULL) {
goto fail;
}
names = tmp;
}
tmpentry = malloc (entry->d_reclen);
if (tmpentry == NULL) {
goto fail;
}
(void) memcpy (tmpentry, entry, entry->d_reclen);
names[namelist_items++] = tmpentry;
}
(void) closedir (d);
if ((namelist_items > 1) && (compar != NULL)) {
qsort (names, namelist_items, sizeof (struct dirent *),
(int (*)(const void *, const void *))compar);
}
*namelist = names;
return namelist_items;
fail:
{
int err = errno;
(void) closedir (d);
while (namelist_items != 0) {
namelist_items--;
free (*namelist[namelist_items]);
}
free (names);
*namelist = NULL;
errno = err;
return -1;
}
}
#endif
#if defined (COROSYNC_SOLARIS) && !defined(HAVE_ALPHASORT)
static int alphasort (const struct dirent **a, const struct dirent **b)
{
return strcmp ((*a)->d_name, (*b)->d_name);
}
#endif
static int interface_find_and_load (
const char *path,
const char *iface_name,
int version,
struct lcr_component_instance **instance_ret,
unsigned int *iface_number)
{
struct lcr_component_instance *instance;
void *dl_handle;
struct dirent **scandir_list;
int scandir_entries;
unsigned int libs_to_scan;
char dl_name[1024];
scandir_entries = scandir (path, &scandir_list, lcr_select_so, alphasort);
if (scandir_entries > 0)
/*
* no error so load the object
*/
for (libs_to_scan = 0; libs_to_scan < scandir_entries; libs_to_scan++) {
/*
* Load objects, scan them, unload them if they are not a match
*/
snprintf (dl_name, sizeof(dl_name), "%s/%s",
path, scandir_list[libs_to_scan]->d_name);
/*
* Don't reload already loaded libraries
*/
if (lcr_lib_loaded (dl_name)) {
continue;
}
dl_handle = dlopen (dl_name, RTLD_LAZY);
if (dl_handle == NULL) {
fprintf(stderr, "%s: open failed: %s\n",
dl_name, dlerror());
continue;
}
instance = lcr_comp_find (iface_name, version, iface_number);
if (instance) {
instance->dl_handle = dl_handle;
strcpy (instance->library_name, dl_name);
goto found;
}
/*
* No matching interfaces found, try next shared object
*/
if (g_component_handle != 0xFFFFFFFF) {
hdb_handle_destroy (&lcr_component_instance_database,
g_component_handle);
g_component_handle = 0xFFFFFFFF;
}
dlclose (dl_handle);
} /* scanning for lcrso loop */
if (scandir_entries > 0) {
int i;
for (i = 0; i < scandir_entries; i++) {
free (scandir_list[i]);
}
free (scandir_list);
}
return -1;
found:
*instance_ret = instance;
if (scandir_entries > 0) {
int i;
for (i = 0; i < scandir_entries; i++) {
free (scandir_list[i]);
}
free (scandir_list);
}
return 0;
}
static unsigned int lcr_initialized = 0;
int lcr_ifact_reference (
hdb_handle_t *iface_handle,
const char *iface_name,
int version,
void **iface,
void *context)
{
struct lcr_iface_instance *iface_instance;
struct lcr_component_instance *instance;
unsigned int iface_number;
unsigned int res;
unsigned int i;
/*
* Determine if the component is already loaded
*/
instance = lcr_comp_find (iface_name, version, &iface_number);
if (instance) {
goto found;
}
if (lcr_initialized == 0) {
lcr_initialized = 1;
defaults_path_build ();
ld_library_path_build ();
ldso_path_build ("/etc", "ld.so.conf");
}
// TODO error checking in this code is weak
/*
* 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);
if (res == 0) {
goto found;
}
}
/*
* No matching interfaces found in all shared objects
*/
return (-1);
found:
*iface = instance->ifaces[iface_number].interfaces;
if (instance->ifaces[iface_number].constructor) {
instance->ifaces[iface_number].constructor (context);
}
hdb_handle_create (&lcr_iface_instance_database,
sizeof (struct lcr_iface_instance),
iface_handle);
hdb_handle_get (&lcr_iface_instance_database,
*iface_handle, (void *)&iface_instance);
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);
}
int lcr_ifact_release (hdb_handle_t handle)
{
struct lcr_iface_instance *iface_instance;
int res = 0;
res = hdb_handle_get (&lcr_iface_instance_database,
handle, (void *)&iface_instance);
if (iface_instance->destructor) {
iface_instance->destructor (iface_instance->context);
}
hdb_handle_put (&lcr_component_instance_database,
iface_instance->component_handle);
hdb_handle_put (&lcr_iface_instance_database, handle);
hdb_handle_destroy (&lcr_iface_instance_database, handle);
return (res);
}
void lcr_component_register (struct lcr_comp *comp)
{
struct lcr_component_instance *instance;
static hdb_handle_t comp_handle;
hdb_handle_create (&lcr_component_instance_database,
sizeof (struct lcr_component_instance),
&comp_handle);
hdb_handle_get (&lcr_component_instance_database,
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,
comp_handle);
g_component_handle = comp_handle;
}
diff --git a/lcr/libtest_a.c b/lcr/libtest_a.c
index 65a9c939..3f5e8f23 100644
--- a/lcr/libtest_a.c
+++ b/lcr/libtest_a.c
@@ -1,167 +1,167 @@
/*
* Copyright (C) 2006 Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <corosync/lcr/lcr_comp.h>
/*
* Version 0 of the interface
*/
static int iface1_constructor (void *context);
static void iface1_destructor (void *context);
static void iface1_func1 (void);
static void iface1_func2 (void);
static void iface1_func3 (void);
/*
* Version 1 of the interface
*/
static int iface1_ver1_constructor (void *context);
static void iface1_ver1_destructor (void *context);
static void iface1_ver1_func1 (void);
static void iface1_ver1_func2 (void);
static void iface1_ver1_func3 (void);
struct iface_list {
void (*iface1_func1)(void);
void (*iface1_func2)(void);
void (*iface1_func3)(void);
};
struct iface_ver1_list {
void (*iface1_ver1_func1)(void);
void (*iface1_ver1_func2)(void);
void (*iface1_ver1_func3)(void);
};
static struct iface_list iface_list = {
.iface1_func1 = iface1_func1,
.iface1_func2 = iface1_func2,
.iface1_func3 = iface1_func3,
};
static struct iface_list iface_ver1_list = {
.iface1_func1 = iface1_ver1_func1,
.iface1_func2 = iface1_ver1_func2,
.iface1_func3 = iface1_ver1_func3,
};
static struct lcr_iface iface1[2] = {
/* version 0 */
{
.name = "A_iface1",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = iface1_constructor,
.destructor = iface1_destructor,
.interfaces = NULL
},
/* version 1 */
{
.name = "A_iface1",
.version = 1,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = iface1_ver1_constructor,
.destructor = iface1_ver1_destructor,
.interfaces = NULL
}
};
static struct lcr_comp test_comp = {
.iface_count = 2,
.ifaces = iface1
};
static int iface1_constructor (void *context)
{
printf ("A - version 0 constructor context %p\n", context);
return (0);
}
static void iface1_destructor (void *context)
{
printf ("A - version 0 destructor context %p\n", context);
}
static void iface1_func1 (void) {
printf ("A - version 0 func1\n");
}
static void iface1_func2 (void) {
printf ("A - version 0 func2\n");
}
static void iface1_func3 (void) {
printf ("A - version 0 func3\n");
}
static int iface1_ver1_constructor (void *context)
{
printf ("A - version 1 constructor context %p\n", context);
return (0);
}
static void iface1_ver1_destructor (void *context)
{
printf ("A - version 1 destructor context %p\n", context);
}
static void iface1_ver1_func1 (void) {
printf ("A - version 1 func1\n");
}
static void iface1_ver1_func2 (void) {
printf ("A - version 1 func2\n");
}
static void iface1_ver1_func3 (void) {
printf ("A - version 1 func3\n");
}
__attribute__ ((constructor)) static void register_this_component (void) {
lcr_interfaces_set (&iface1[0], &iface_list);
lcr_interfaces_set (&iface1[1], &iface_ver1_list);
lcr_component_register (&test_comp);
}
diff --git a/lcr/libtest_b.c b/lcr/libtest_b.c
index cdabae8b..9ef68a22 100644
--- a/lcr/libtest_b.c
+++ b/lcr/libtest_b.c
@@ -1,174 +1,174 @@
/*
* Copyright (C) 2006 Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <corosync/lcr/lcr_comp.h>
/*
* Version 0 of the interface
*/
static int iface1_constructor (void *context);
static void iface1_destructor (void *context);
static void iface1_func1 (void);
static void iface1_func2 (void);
static void iface1_func3 (void);
/*
* Version 1 of the interface
*/
static int iface1_ver1_constructor (void *context);
static void iface1_ver1_destructor (void *context);
static void iface1_ver1_func1 (void);
static void iface1_ver1_func2 (void);
static void iface1_ver1_func3 (void);
struct iface_list {
void (*iface1_func1)(void);
void (*iface1_func2)(void);
void (*iface1_func3)(void);
};
struct iface_ver1_list {
void (*iface1_ver1_func1)(void);
void (*iface1_ver1_func2)(void);
void (*iface1_ver1_func3)(void);
};
struct iface_list iface_list = {
.iface1_func1 = iface1_func1,
.iface1_func2 = iface1_func2,
.iface1_func3 = iface1_func3,
};
struct iface_list iface_ver1_list = {
.iface1_func1 = iface1_ver1_func1,
.iface1_func2 = iface1_ver1_func2,
.iface1_func3 = iface1_ver1_func3,
};
struct lcr_iface iface1[2]= {
/*
* Version 0
*/
{
.name = "B_iface1",
.version = 0,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = iface1_constructor,
.destructor = iface1_destructor,
.interfaces = NULL
},
/*
* Version 1
*/
{
.name = "B_iface1",
.version = 1,
.versions_replace = 0,
.versions_replace_count = 0,
.dependencies = 0,
.dependency_count = 0,
.constructor = iface1_ver1_constructor,
.destructor = iface1_ver1_destructor,
.interfaces = NULL
}
};
struct lcr_comp test_comp = {
.iface_count = 2,
.ifaces = iface1
};
static int iface1_constructor (void *context)
{
printf ("B - version 0 constructor context %p\n", context);
return (0);
}
static void iface1_destructor (void *context)
{
printf ("B - version 0 destructor context %p\n", context);
}
static void iface1_func1 (void) {
printf ("B - version 0 func1\n");
}
static void iface1_func2 (void) {
printf ("B - version 0 func2\n");
}
static void iface1_func3 (void) {
printf ("B - version 0 func3\n");
}
static int iface1_ver1_constructor (void *context)
{
printf ("B - version 1 constructor context %p\n", context);
return (0);
}
static void iface1_ver1_destructor (void *context)
{
printf ("B - version 1 destructor context %p\n", context);
}
static void iface1_ver1_func1 (void) {
printf ("B - version 1 func1\n");
}
static void iface1_ver1_func2 (void) {
printf ("B - version 1 func2\n");
}
static void iface1_ver1_func3 (void) {
printf ("B - version 1 func3\n");
}
__attribute__ ((constructor)) static void register_this_component (void)
{
lcr_interfaces_set (&iface1[0], &iface_list);
lcr_interfaces_set (&iface1[1], &iface_ver1_list);
lcr_component_register (&test_comp);
}
diff --git a/lcr/test.c b/lcr/test.c
index 0c73c914..4c01ba29 100644
--- a/lcr/test.c
+++ b/lcr/test.c
@@ -1,129 +1,129 @@
/*
* Copyright (C) 2006 Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <assert.h>
#include <unistd.h>
#include <corosync/hdb.h>
#include <corosync/lcr/lcr_ifact.h>
struct iface {
void (*func1) (void);
void (*func2) (void);
void (*func3) (void);
};
int main (void) {
hdb_handle_t a_ifact_handle_ver0;
hdb_handle_t b_ifact_handle_ver0;
struct iface *a_iface_ver0;
struct iface *a_iface_ver1;
void *a_iface_ver0_p;
void *a_iface_ver1_p;
hdb_handle_t a_ifact_handle_ver1;
hdb_handle_t b_ifact_handle_ver1;
struct iface *b_iface_ver0;
struct iface *b_iface_ver1;
void *b_iface_ver0_p;
void *b_iface_ver1_p;
unsigned int res;
/*
* Reference version 0 and 1 of A and B interfaces
*/
res = lcr_ifact_reference (
&a_ifact_handle_ver0,
"A_iface1",
0, /* version 0 */
&a_iface_ver0_p,
(void *)0xaaaa0000);
assert (res == 0);
a_iface_ver0 = (struct iface *)a_iface_ver0_p;
res = lcr_ifact_reference (
&b_ifact_handle_ver0,
"B_iface1",
0, /* version 0 */
&b_iface_ver0_p,
(void *)0xbbbb0000);
assert (res == 0);
b_iface_ver0 = (struct iface *)b_iface_ver0_p;
res = lcr_ifact_reference (
&a_ifact_handle_ver1,
"A_iface1",
1, /* version 1 */
&a_iface_ver1_p,
(void *)0xaaaa1111);
assert (res == 0);
a_iface_ver1 = (struct iface *)a_iface_ver1_p;
res = lcr_ifact_reference (
&b_ifact_handle_ver1,
"B_iface1",
1, /* version 1 */
&b_iface_ver1_p,
(void *)0xbbbb1111);
assert (res == 0);
b_iface_ver1 = (struct iface *)b_iface_ver1_p;
a_iface_ver0->func1();
a_iface_ver0->func2();
a_iface_ver0->func3();
lcr_ifact_release (a_ifact_handle_ver0);
a_iface_ver1->func1();
a_iface_ver1->func2();
a_iface_ver1->func3();
lcr_ifact_release (a_ifact_handle_ver1);
b_iface_ver0->func1();
b_iface_ver0->func2();
b_iface_ver0->func3();
lcr_ifact_release (b_ifact_handle_ver0);
b_iface_ver1->func1();
b_iface_ver1->func2();
b_iface_ver1->func3();
lcr_ifact_release (b_ifact_handle_ver1);
return (0);
}
diff --git a/lcr/uic.c b/lcr/uic.c
index fb516c47..5c4b1390 100755
--- a/lcr/uic.c
+++ b/lcr/uic.c
@@ -1,158 +1,158 @@
/*
* Copyright (c) 2006 Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <pthread.h>
#include <sys/poll.h>
#include <string.h>
#if defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS)
-/* SUN_LEN is broken for abstract namespace
+/* SUN_LEN is broken for abstract namespace
*/
#define AIS_SUN_LEN(a) sizeof(*(a))
#else
#define AIS_SUN_LEN(a) SUN_LEN(a)
#endif
#ifdef COROSYNC_LINUX
static const char *socketname = "lcr.socket";
#else
static const char *socketname = SOCKETDIR "/lcr.socket";
#endif
static int uic_connect (int *fd);
static int uic_msg_send (int fd, void *msg);
int uic_connect (int *fd)
{
int res;
struct sockaddr_un addr;
memset (&addr, 0, sizeof (struct sockaddr_un));
#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
addr.sun_len = sizeof(struct sockaddr_un);
#endif
addr.sun_family = PF_UNIX;
#if defined(COROSYNC_LINUX)
strcpy (addr.sun_path + 1, socketname);
#else
strcpy (addr.sun_path, socketname);
#endif
*fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (*fd == -1) {
return -errno;
}
res = connect (*fd, (struct sockaddr *)&addr, AIS_SUN_LEN(&addr));
if (res == -1) {
return -errno;
}
return 0;
}
struct uic_req_msg {
int len;
char msg[0];
};
static int uic_msg_send (int fd, void *msg)
{
struct msghdr msg_send;
struct iovec iov_send[2];
struct uic_req_msg req_msg;
ssize_t send_res;
int res;
req_msg.len = strlen (msg) + 1;
iov_send[0].iov_base = (void *)&req_msg;
iov_send[0].iov_len = sizeof (struct uic_req_msg);
iov_send[1].iov_base = msg;
iov_send[1].iov_len = req_msg.len;
msg_send.msg_iov = iov_send;
msg_send.msg_iovlen = 2;
msg_send.msg_name = 0;
msg_send.msg_namelen = 0;
#ifndef COROSYNC_SOLARIS
msg_send.msg_control = 0;
msg_send.msg_controllen = 0;
msg_send.msg_flags = 0;
#else
msg_send.msg_accrights = NULL;
msg_send.msg_accrightslen = 0;
#endif
retry_send:
send_res = sendmsg (fd, &msg_send, 0);
if (send_res == -1 && errno == EINTR) {
goto retry_send;
}
if (send_res == -1) {
res = -errno;
} else {
res = (int)send_res;
}
return (res);
}
int main (void)
{
int client_fd;
int res;
char command[128] = "livereplace ckpt version2";
res = uic_connect (&client_fd);
if (res != 0) {
printf ("Couldn't connect to live replacement service\n");
}
uic_msg_send (client_fd, (void *)command);
return 0;
}
diff --git a/lcr/uis.c b/lcr/uis.c
index 02ec8439..738431ec 100755
--- a/lcr/uis.c
+++ b/lcr/uis.c
@@ -1,192 +1,192 @@
/*
* Copyright (c) 2006 Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sched.h>
#include <time.h>
#include <pthread.h>
#include <sys/poll.h>
#include <string.h>
#define SERVER_BACKLOG 5
#if defined(COROSYNC_LINUX) || defined(COROSYNC_SOLARIS)
-/* SUN_LEN is broken for abstract namespace
+/* SUN_LEN is broken for abstract namespace
*/
#define AIS_SUN_LEN(a) sizeof(*(a))
#else
#define AIS_SUN_LEN(a) SUN_LEN(a)
#endif
#ifdef COROSYNC_LINUX
static const char *socketname = "lcr.socket";
#else
static const char *socketname = SOCKETDIR "/lcr.socket";
#endif
static void uis_lcr_bind (int *server_fd)
{
int fd;
struct sockaddr_un un_addr;
int res;
/*
* Create socket for lcr clients, name socket, listen for connections
*/
fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
printf ("lcr_bind failed\n");
};
#if !defined(COROSYNC_LINUX)
unlink(socketname);
#endif
memset (&un_addr, 0, sizeof (struct sockaddr_un));
#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
un_addr.sun_len = sizeof(struct sockaddr_un);
#endif
un_addr.sun_family = AF_UNIX;
#if defined(COROSYNC_LINUX)
strcpy (un_addr.sun_path + 1, socketname);
#else
strcpy (un_addr.sun_path, socketname);
#endif
res = bind (fd, (struct sockaddr *)&un_addr, AIS_SUN_LEN(&un_addr));
if (res) {
printf ("Could not bind AF_UNIX: %s\n", strerror (errno));
}
listen (fd, SERVER_BACKLOG);
*server_fd = fd;
}
struct uis_commands {
const char *command;
void (*cmd_handler) (char *);
};
static void cmd1 (char *cmd) {
printf ("cmd1 executed with cmd line %s\n", cmd);
}
struct uis_commands uis_commands[] = {
{
"cmd1", cmd1
}
};
struct uis_req_msg {
int len;
char msg[0];
};
static void lcr_uis_dispatch (int fd)
{
struct uis_req_msg header;
char msg_contents[512];
ssize_t readsize;
/*
* TODO this doesn't handle short reads
*/
readsize = read (fd, &header, sizeof (header));
if (readsize == -1) {
return;
}
readsize = read (fd, msg_contents, sizeof (msg_contents));
if (readsize == -1) {
return;
}
printf ("msg contents %s\n", msg_contents);
}
static void *lcr_uis_server (void *data)
{
struct pollfd ufds[2];
struct sockaddr_un un_addr;
socklen_t addrlen;
int nfds = 1;
#ifdef COROSYNC_LINUX
int on = 1;
#endif
/*
* Main acceptance and dispatch loop
*/
uis_lcr_bind (&ufds[0].fd);
printf ("UIS server thread started %d\n", ufds[0].fd);
ufds[0].events = POLLIN;
ufds[1].events = POLLOUT;
for (;;) {
int res = poll (ufds, nfds, -1);
if (res == 0 || (res < 0 && errno == EINTR))
continue;
if (res < 0)
return NULL;
if (nfds == 1 && ufds[0].revents & POLLIN) {
ufds[1].fd = accept (ufds[0].fd,
(struct sockaddr *)&un_addr, &addrlen);
-#ifdef COROSYNC_LINUX
+#ifdef COROSYNC_LINUX
setsockopt(ufds[1].fd, SOL_SOCKET, SO_PASSCRED,
&on, sizeof (on));
#endif
- nfds = 2;
+ nfds = 2;
}
if (ufds[0].revents & POLLIN) {
lcr_uis_dispatch (ufds[1].fd);
}
}
}
__attribute__ ((constructor)) static int lcr_uis_ctors (void)
{
pthread_t thread;
pthread_create (&thread, NULL, lcr_uis_server, NULL);
return (0);
}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index de13c9be..5b3644ab 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,120 +1,120 @@
#
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
AM_CFLAGS = -fPIC
AM_LDFLAGS = -lpthread
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
lib_LIBRARIES = libcpg.a libconfdb.a libevs.a libcfg.a libquorum.a \
libvotequorum.a libpload.a libcoroipcc.a
SHARED_LIBS = $(lib_LIBRARIES:%.a=%.so.$(SONAME))
SHARED_LIBS_SO = $(lib_LIBRARIES:%.a=%.so)
SHARED_LIBS_SO_TWO = $(lib_LIBRARIES:%.a=%.so.$(SOMAJOR))
libcpg_a_SOURCES = coroipcc.c cpg.c
libcfg_a_SOURCES = coroipcc.c cfg.c
libevs_a_SOURCES = coroipcc.c evs.c
libpload_a_SOURCES = coroipcc.c pload.c
libquorum_a_SOURCES = coroipcc.c quorum.c
libvotequorum_a_SOURCES = coroipcc.c votequorum.c
libconfdb_a_SOURCES = coroipcc.c confdb.c sa-confdb.c
libcoroipcc_a_SOURCES = coroipcc.c
noinst_HEADERS = sa-confdb.h util.h \
libcfg.versions libconfdb.versions \
libcoroipcc.versions libcpg.versions \
libevs.versions libpload.versions \
libquorum.versions libvotequorum.versions
../lcr/lcr_ifact.o:
$(MAKE) -C ../lcr lcr_ifact.o
if BUILD_DARWIN
libcoroipcc.so.$(SONAME): coroipcc.o
$(CC) $(LDFLAGS) $(DARWIN_OPTS) coroipcc.o -o $@ $(AM_LDFLAGS)
-libconfdb.so.$(SONAME): coroipcc.o confdb.o sa-confdb.o
+libconfdb.so.$(SONAME): coroipcc.o confdb.o sa-confdb.o
$(CC) $(LDFLAGS) $(DARWIN_OPTS) coroipcc.o confdb.o \
sa-confdb.o ../lcr/lcr_ifact.o -o $@ -ldl $(AM_LDFLAGS)
lib%.so.$(SONAME): coroipcc.o %.o
$(CC) $(DARWIN_OPTS) $^ -o $@
else
libcoroipcc.so.$(SONAME): coroipcc.o
$(CC) -shared -o $@ \
-Wl,-soname=libcoroipcc.so.$(SOMAJOR) \
-Wl,-version-script=$(srcdir)/libcoroipcc.versions \
$^ $(LDFLAGS) $(AM_LDFLAGS)
ln -sf libcoroipcc.so.$(SONAME) libcoroipcc.so
ln -sf libcoroipcc.so.$(SONAME) libcoroipcc.so.$(SOMAJOR)
libconfdb.so.$(SONAME): coroipcc.o confdb.o sa-confdb.o ../lcr/lcr_ifact.o
$(CC) -shared -o $@ \
-Wl,-soname=libconfdb.so.$(SOMAJOR) \
-Wl,-version-script=$(srcdir)/libconfdb.versions \
$^ $(LDFLAGS) $(OS_DYFLAGS) -ldl $(AM_LDFLAGS)
ln -sf libconfdb.so.$(SONAME) libconfdb.so
ln -sf libconfdb.so.$(SONAME) libconfdb.so.$(SOMAJOR)
lib%.so.$(SONAME): coroipcc.o %.o
$(CC) -shared -o $@ \
-Wl,-soname=lib$*.so.$(SOMAJOR) \
-Wl,-version-script=$(srcdir)/lib$*.versions \
$^ $(LDFLAGS) $(AM_LDFLAGS)
ln -sf lib$*.so.$(SONAME) lib$*.so
ln -sf lib$*.so.$(SONAME) lib$*.so.$(SOMAJOR)
endif
all-local: $(SHARED_LIBS)
@echo Built shared libs
install-exec-local:
$(INSTALL) -d $(DESTDIR)/$(libdir)
$(INSTALL) -m 755 $(SHARED_LIBS) $(DESTDIR)/$(libdir)
cp -a $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO) $(DESTDIR)/$(libdir)
uninstall-local:
cd $(DESTDIR)/$(libdir)/ && \
rm -f $(SHARED_LIBS) $(SHARED_LIBS_SO) $(SHARED_LIBS_SO_TWO)
clean-local:
rm -f *.o *.a *.so* *.da *.bb *.bbg
diff --git a/lib/coroipcc.c b/lib/coroipcc.c
index 22254b02..ecb856cb 100644
--- a/lib/coroipcc.c
+++ b/lib/coroipcc.c
@@ -1,1135 +1,1135 @@
/*
* vi: set autoindent tabstop=4 shiftwidth=4 :
*
* Copyright (c) 2002-2006 MontaVista Software, Inc.
* Copyright (c) 2006-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/un.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <assert.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <corosync/corotypes.h>
#include <corosync/ipc_gen.h>
#include <corosync/coroipcc.h>
enum SA_HANDLE_STATE {
SA_HANDLE_STATE_EMPTY,
SA_HANDLE_STATE_PENDINGREMOVAL,
SA_HANDLE_STATE_ACTIVE
};
struct saHandle {
int state;
void *instance;
int refCount;
uint32_t check;
};
struct ipc_segment {
int fd;
int shmid;
int semid;
int flow_control_state;
struct control_buffer *control_buffer;
char *request_buffer;
char *response_buffer;
char *dispatch_buffer;
size_t control_size;
size_t request_size;
size_t response_size;
size_t dispatch_size;
uid_t euid;
};
#if defined(COROSYNC_LINUX)
-/* SUN_LEN is broken for abstract namespace
+/* SUN_LEN is broken for abstract namespace
*/
#define AIS_SUN_LEN(a) sizeof(*(a))
#else
#define AIS_SUN_LEN(a) SUN_LEN(a)
#endif
#ifdef SO_NOSIGPIPE
void socket_nosigpipe(int s)
{
int on = 1;
setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(on));
}
-#endif
+#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
static int
coroipcc_send (
int s,
void *msg,
size_t len)
{
int result;
struct msghdr msg_send;
struct iovec iov_send;
char *rbuf = msg;
int processed = 0;
msg_send.msg_iov = &iov_send;
msg_send.msg_iovlen = 1;
msg_send.msg_name = 0;
msg_send.msg_namelen = 0;
msg_send.msg_control = 0;
msg_send.msg_controllen = 0;
msg_send.msg_flags = 0;
retry_send:
iov_send.iov_base = &rbuf[processed];
iov_send.iov_len = len - processed;
result = sendmsg (s, &msg_send, MSG_NOSIGNAL);
/*
* return immediately on any kind of syscall error that maps to
* CS_ERR if no part of message has been sent
*/
if (result == -1 && processed == 0) {
if (errno == EINTR) {
goto error_exit;
}
if (errno == EAGAIN) {
goto error_exit;
}
if (errno == EFAULT) {
goto error_exit;
}
}
/*
* retry read operations that are already started except
* for fault in that case, return ERR_LIBRARY
*/
if (result == -1 && processed > 0) {
if (errno == EINTR) {
goto retry_send;
}
if (errno == EAGAIN) {
goto retry_send;
}
if (errno == EFAULT) {
goto error_exit;
}
}
/*
* return ERR_LIBRARY on any other syscall error
*/
if (result == -1) {
goto error_exit;
}
processed += result;
if (processed != len) {
goto retry_send;
}
return (0);
error_exit:
return (-1);
}
static int
coroipcc_recv (
int s,
void *msg,
size_t len)
{
int error = 0;
int result;
struct msghdr msg_recv;
struct iovec iov_recv;
char *rbuf = msg;
int processed = 0;
msg_recv.msg_iov = &iov_recv;
msg_recv.msg_iovlen = 1;
msg_recv.msg_name = 0;
msg_recv.msg_namelen = 0;
msg_recv.msg_control = 0;
msg_recv.msg_controllen = 0;
msg_recv.msg_flags = 0;
retry_recv:
iov_recv.iov_base = (void *)&rbuf[processed];
iov_recv.iov_len = len - processed;
result = recvmsg (s, &msg_recv, MSG_NOSIGNAL|MSG_WAITALL);
if (result == -1 && errno == EINTR) {
goto retry_recv;
}
if (result == -1 && errno == EAGAIN) {
goto retry_recv;
}
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
/* On many OS poll never return POLLHUP or POLLERR.
* EOF is detected when recvmsg return 0.
*/
if (result == 0) {
error = -1;
goto error_exit;
}
#endif
if (result == -1 || result == 0) {
error = -1;
goto error_exit;
}
processed += result;
if (processed != len) {
goto retry_recv;
}
assert (processed == len);
error_exit:
return (0);
}
-static int
+static int
priv_change_send (struct ipc_segment *ipc_segment)
{
char buf_req;
mar_req_priv_change req_priv_change;
unsigned int res;
-
+
req_priv_change.euid = geteuid();
/*
* Don't resend request unless euid has changed
*/
if (ipc_segment->euid == req_priv_change.euid) {
return (0);
}
req_priv_change.egid = getegid();
buf_req = MESSAGE_REQ_CHANGE_EUID;
res = coroipcc_send (ipc_segment->fd, &buf_req, 1);
if (res == -1) {
return (-1);
}
res = coroipcc_send (ipc_segment->fd, &req_priv_change,
sizeof (req_priv_change));
if (res == -1) {
return (-1);
}
ipc_segment->euid = req_priv_change.euid;
return (0);
}
#if defined(_SEM_SEMUN_UNDEFINED)
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif
-
+
static int
circular_memory_map (char *path, const char *file, void **buf, size_t bytes)
{
int fd;
void *addr_orig;
void *addr;
int res;
sprintf (path, "/dev/shm/%s", file);
-
+
fd = mkstemp (path);
if (fd == -1) {
sprintf (path, "/var/run/%s", file);
fd = mkstemp (path);
if (fd == -1) {
return (-1);
}
}
res = ftruncate (fd, bytes);
addr_orig = mmap (NULL, bytes << 1, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
+
if (addr_orig == MAP_FAILED) {
return (-1);
}
-
+
addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
-
+
if (addr != addr_orig) {
return (-1);
}
-
+
addr = mmap (((char *)addr_orig) + bytes,
bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
-
+
res = close (fd);
if (res) {
return (-1);
}
*buf = addr_orig;
return (0);
}
-
+
static void
memory_unmap (void *addr, size_t bytes)
{
int res;
-
+
res = munmap (addr, bytes);
}
static int
memory_map (char *path, const char *file, void **buf, size_t bytes)
{
int fd;
void *addr_orig;
void *addr;
int res;
sprintf (path, "/dev/shm/%s", file);
-
+
fd = mkstemp (path);
if (fd == -1) {
sprintf (path, "/var/run/%s", file);
fd = mkstemp (path);
if (fd == -1) {
return (-1);
}
}
res = ftruncate (fd, bytes);
addr_orig = mmap (NULL, bytes, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
+
if (addr_orig == MAP_FAILED) {
return (-1);
}
-
+
addr = mmap (addr_orig, bytes, PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd, 0);
-
+
if (addr != addr_orig) {
return (-1);
}
-
+
res = close (fd);
if (res) {
return (-1);
}
*buf = addr_orig;
return (0);
}
-
+
extern cs_error_t
coroipcc_service_connect (
const char *socket_name,
unsigned int service,
size_t request_size,
size_t response_size,
size_t dispatch_size,
void **ipc_context)
{
int request_fd;
struct sockaddr_un address;
cs_error_t error;
struct ipc_segment *ipc_segment;
key_t semkey = 0;
int res;
mar_req_setup_t req_setup;
mar_res_setup_t res_setup;
union semun semun;
char control_map_path[128];
char request_map_path[128];
char response_map_path[128];
char dispatch_map_path[128];
res_setup.error = CS_ERR_LIBRARY;
request_fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (request_fd == -1) {
return (-1);
}
memset (&address, 0, sizeof (struct sockaddr_un));
#if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
address.sun_len = sizeof(struct sockaddr_un);
#endif
address.sun_family = PF_UNIX;
#if defined(COROSYNC_LINUX)
sprintf (address.sun_path + 1, "%s", socket_name);
#else
sprintf (address.sun_path, "%s/%s", SOCKETDIR, socket_name);
#endif
res = connect (request_fd, (struct sockaddr *)&address,
AIS_SUN_LEN(&address));
if (res == -1) {
close (request_fd);
return (CS_ERR_TRY_AGAIN);
}
ipc_segment = malloc (sizeof (struct ipc_segment));
if (ipc_segment == NULL) {
close (request_fd);
return (-1);
}
bzero (ipc_segment, sizeof (struct ipc_segment));
/*
* Allocate a semaphore segment
*/
while (1) {
semkey = random();
ipc_segment->euid = geteuid ();
if ((ipc_segment->semid
= semget (semkey, 3, IPC_CREAT|IPC_EXCL|0600)) != -1) {
break;
}
if (errno != EEXIST) {
goto error_exit;
}
}
semun.val = 0;
res = semctl (ipc_segment->semid, 0, SETVAL, semun);
if (res != 0) {
goto error_exit;
}
res = semctl (ipc_segment->semid, 1, SETVAL, semun);
if (res != 0) {
goto error_exit;
}
res = memory_map (
control_map_path,
"control_buffer-XXXXXX",
(void *)&ipc_segment->control_buffer,
8192);
res = memory_map (
request_map_path,
"request_buffer-XXXXXX",
(void *)&ipc_segment->request_buffer,
request_size);
res = memory_map (
response_map_path,
"response_buffer-XXXXXX",
(void *)&ipc_segment->response_buffer,
response_size);
res = circular_memory_map (
dispatch_map_path,
"dispatch_buffer-XXXXXX",
(void *)&ipc_segment->dispatch_buffer,
dispatch_size);
/*
* Initialize IPC setup message
*/
req_setup.service = service;
strcpy (req_setup.control_file, control_map_path);
strcpy (req_setup.request_file, request_map_path);
strcpy (req_setup.response_file, response_map_path);
strcpy (req_setup.dispatch_file, dispatch_map_path);
req_setup.control_size = 8192;
req_setup.request_size = request_size;
req_setup.response_size = response_size;
req_setup.dispatch_size = dispatch_size;
req_setup.semkey = semkey;
error = coroipcc_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
if (error != 0) {
goto error_exit;
}
error = coroipcc_recv (request_fd, &res_setup, sizeof (mar_res_setup_t));
if (error != 0) {
goto error_exit;
}
ipc_segment->fd = request_fd;
ipc_segment->flow_control_state = 0;
if (res_setup.error == CS_ERR_TRY_AGAIN) {
goto error_exit;
}
ipc_segment->control_size = 8192;
ipc_segment->request_size = request_size;
ipc_segment->response_size = response_size;
ipc_segment->dispatch_size = dispatch_size;
*ipc_context = ipc_segment;
return (res_setup.error);
error_exit:
close (request_fd);
if (ipc_segment->semid > 0)
semctl (ipc_segment->semid, 0, IPC_RMID);
return (res_setup.error);
}
cs_error_t
coroipcc_service_disconnect (
void *ipc_context)
{
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
shutdown (ipc_segment->fd, SHUT_RDWR);
close (ipc_segment->fd);
/*
* << 1 (or multiplied by 2) because this is a wrapped memory buffer
*/
memory_unmap (ipc_segment->control_buffer, ipc_segment->control_size);
memory_unmap (ipc_segment->request_buffer, ipc_segment->request_size);
memory_unmap (ipc_segment->response_buffer, ipc_segment->response_size);
memory_unmap (ipc_segment->dispatch_buffer, (ipc_segment->dispatch_size) << 1);
free (ipc_segment);
return (CS_OK);
}
int
coroipcc_dispatch_flow_control_get (
void *ipc_context)
{
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
return (ipc_segment->flow_control_state);
}
int
coroipcc_fd_get (void *ipc_ctx)
{
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
return (ipc_segment->fd);
}
int
coroipcc_dispatch_get (void *ipc_ctx, void **data, int timeout)
{
struct pollfd ufds;
int poll_events;
char buf;
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
int res;
char buf_two = 1;
char *data_addr;
ufds.fd = ipc_segment->fd;
ufds.events = POLLIN;
ufds.revents = 0;
retry_poll:
poll_events = poll (&ufds, 1, timeout);
if (poll_events == -1 && errno == EINTR) {
goto retry_poll;
- } else
+ } else
if (poll_events == -1) {
return (-1);
} else
if (poll_events == 0) {
return (0);
}
if (poll_events == 1 && (ufds.revents & (POLLERR|POLLHUP))) {
return (-1);
}
retry_recv:
res = recv (ipc_segment->fd, &buf, 1, 0);
if (res == -1 && errno == EINTR) {
goto retry_recv;
} else
if (res == -1) {
return (-1);
}
if (res == 0) {
return (-1);
}
ipc_segment->flow_control_state = 0;
if (buf == 1 || buf == 2) {
ipc_segment->flow_control_state = 1;
}
/*
* Notify executive to flush any pending dispatch messages
*/
if (ipc_segment->flow_control_state) {
buf_two = MESSAGE_REQ_OUTQ_FLUSH;
res = coroipcc_send (ipc_segment->fd, &buf_two, 1);
assert (res == 0); //TODO
}
/*
* This is just a notification of flow control starting at the addition
* of a new pending message, not a message to dispatch
*/
if (buf == 2) {
return (0);
}
if (buf == 3) {
return (0);
}
data_addr = ipc_segment->dispatch_buffer;
data_addr = &data_addr[ipc_segment->control_buffer->read];
*data = (void *)data_addr;
return (1);
}
int
coroipcc_dispatch_put (void *ipc_ctx)
{
struct sembuf sop;
mar_res_header_t *header;
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_ctx;
int res;
char *addr;
unsigned int read_idx;
sop.sem_num = 2;
sop.sem_op = -1;
sop.sem_flg = 0;
retry_semop:
res = semop (ipc_segment->semid, &sop, 1);
if (res == -1 && errno == EINTR) {
goto retry_semop;
} else
if (res == -1 && errno == EACCES) {
priv_change_send (ipc_segment);
goto retry_semop;
} else
if (res == -1) {
return (-1);
}
addr = ipc_segment->dispatch_buffer;
read_idx = ipc_segment->control_buffer->read;
header = (mar_res_header_t *) &addr[read_idx];
ipc_segment->control_buffer->read =
(read_idx + header->size) % ipc_segment->dispatch_size;
return (0);
}
static cs_error_t
coroipcc_msg_send (
void *ipc_context,
const struct iovec *iov,
unsigned int iov_len)
{
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
struct sembuf sop;
int i;
int res;
int req_buffer_idx = 0;
for (i = 0; i < iov_len; i++) {
memcpy (&ipc_segment->request_buffer[req_buffer_idx],
iov[i].iov_base,
iov[i].iov_len);
req_buffer_idx += iov[i].iov_len;
}
/*
* Signal semaphore #0 indicting a new message from client
* to server request queue
*/
sop.sem_num = 0;
sop.sem_op = 1;
sop.sem_flg = 0;
retry_semop:
res = semop (ipc_segment->semid, &sop, 1);
if (res == -1 && errno == EINTR) {
goto retry_semop;
} else
if (res == -1 && errno == EACCES) {
priv_change_send (ipc_segment);
goto retry_semop;
} else
if (res == -1) {
return (CS_ERR_LIBRARY);
}
return (CS_OK);
}
static cs_error_t
coroipcc_reply_receive (
void *ipc_context,
void *res_msg, size_t res_len)
{
struct sembuf sop;
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
int res;
/*
* Wait for semaphore #1 indicating a new message from server
* to client in the response queue
*/
sop.sem_num = 1;
sop.sem_op = -1;
sop.sem_flg = 0;
retry_semop:
res = semop (ipc_segment->semid, &sop, 1);
if (res == -1 && errno == EINTR) {
goto retry_semop;
} else
if (res == -1 && errno == EACCES) {
priv_change_send (ipc_segment);
goto retry_semop;
} else
if (res == -1) {
return (CS_ERR_LIBRARY);
}
memcpy (res_msg, ipc_segment->response_buffer, res_len);
return (CS_OK);
}
static cs_error_t
coroipcc_reply_receive_in_buf (
void *ipc_context,
void **res_msg)
{
struct sembuf sop;
struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
int res;
/*
* Wait for semaphore #1 indicating a new message from server
* to client in the response queue
*/
sop.sem_num = 1;
sop.sem_op = -1;
sop.sem_flg = 0;
retry_semop:
res = semop (ipc_segment->semid, &sop, 1);
if (res == -1 && errno == EINTR) {
goto retry_semop;
} else
if (res == -1 && errno == EACCES) {
priv_change_send (ipc_segment);
goto retry_semop;
} else
if (res == -1) {
return (CS_ERR_LIBRARY);
}
*res_msg = (char *)ipc_segment->response_buffer;
return (CS_OK);
}
cs_error_t
coroipcc_msg_send_reply_receive (
void *ipc_context,
const struct iovec *iov,
unsigned int iov_len,
void *res_msg,
size_t res_len)
{
cs_error_t res;
res = coroipcc_msg_send (ipc_context, iov, iov_len);
if (res != CS_OK) {
return (res);
}
res = coroipcc_reply_receive (ipc_context, res_msg, res_len);
if (res != CS_OK) {
return (res);
}
return (CS_OK);
}
cs_error_t
coroipcc_msg_send_reply_receive_in_buf (
void *ipc_context,
const struct iovec *iov,
unsigned int iov_len,
void **res_msg)
{
unsigned int res;
res = coroipcc_msg_send (ipc_context, iov, iov_len);
if (res != CS_OK) {
return (res);
}
res = coroipcc_reply_receive_in_buf (ipc_context, res_msg);
if (res != CS_OK) {
return (res);
}
return (CS_OK);
}
#if defined(HAVE_PTHREAD_SPIN_LOCK)
static void hdb_lock (struct saHandleDatabase *hdb)
{
pthread_spin_lock (&hdb->lock);
}
static void hdb_unlock (struct saHandleDatabase *hdb)
{
pthread_spin_unlock (&hdb->lock);
}
void saHandleDatabaseLock_init (struct saHandleDatabase *hdb)
{
pthread_spin_init (&hdb->lock, 0);
}
#else
static void hdb_lock (struct saHandleDatabase *hdb)
{
pthread_mutex_lock (&hdb->lock);
}
static void hdb_unlock (struct saHandleDatabase *hdb)
{
pthread_mutex_unlock (&hdb->lock);
}
void saHandleDatabaseLock_init (struct saHandleDatabase *hdb)
{
pthread_mutex_init (&hdb->lock, NULL);
}
#endif
cs_error_t
coroipcc_zcb_alloc (
void *ipc_context,
void **buffer,
size_t size,
size_t header_size)
{
void *buf = NULL;
char path[128];
unsigned int res;
mar_req_coroipcc_zc_alloc_t req_coroipcc_zc_alloc;
mar_res_header_t res_coroipcs_zc_alloc;
size_t map_size;
struct iovec iovec;
struct coroipcs_zc_header *hdr;
map_size = size + header_size + sizeof (struct coroipcs_zc_header);
res = memory_map (path, "cpg_zc-XXXXXX", &buf, size);
assert (res != -1);
req_coroipcc_zc_alloc.header.size = sizeof (mar_req_coroipcc_zc_alloc_t);
req_coroipcc_zc_alloc.header.id = ZC_ALLOC_HEADER;
req_coroipcc_zc_alloc.map_size = map_size;
strcpy (req_coroipcc_zc_alloc.path_to_file, path);
iovec.iov_base = &req_coroipcc_zc_alloc;
iovec.iov_len = sizeof (mar_req_coroipcc_zc_alloc_t);
res = coroipcc_msg_send_reply_receive (
ipc_context,
&iovec,
1,
&res_coroipcs_zc_alloc,
sizeof (mar_res_header_t));
hdr = (struct coroipcs_zc_header *)buf;
hdr->map_size = map_size;
*buffer = ((char *)buf) + sizeof (struct coroipcs_zc_header);
return (CS_OK);
}
cs_error_t
coroipcc_zcb_free (
void *ipc_context,
void *buffer)
{
mar_req_coroipcc_zc_free_t req_coroipcc_zc_free;
mar_res_header_t res_coroipcs_zc_free;
struct iovec iovec;
unsigned int res;
struct coroipcs_zc_header *header = (struct coroipcs_zc_header *)((char *)buffer - sizeof (struct coroipcs_zc_header));
req_coroipcc_zc_free.header.size = sizeof (mar_req_coroipcc_zc_free_t);
req_coroipcc_zc_free.header.id = ZC_FREE_HEADER;
req_coroipcc_zc_free.map_size = header->map_size;
req_coroipcc_zc_free.server_address = header->server_address;
iovec.iov_base = &req_coroipcc_zc_free;
iovec.iov_len = sizeof (mar_req_coroipcc_zc_free_t);
res = coroipcc_msg_send_reply_receive (
ipc_context,
&iovec,
1,
&res_coroipcs_zc_free,
sizeof (mar_res_header_t));
munmap (header, header->map_size);
return (CS_OK);
}
cs_error_t
coroipcc_zcb_msg_send_reply_receive (
void *ipc_context,
void *msg,
void *res_msg,
size_t res_len)
{
mar_req_coroipcc_zc_execute_t req_coroipcc_zc_execute;
struct coroipcs_zc_header *hdr;
struct iovec iovec;
cs_error_t res;
hdr = (struct coroipcs_zc_header *)(((char *)msg) - sizeof (struct coroipcs_zc_header));
req_coroipcc_zc_execute.header.size = sizeof (mar_req_coroipcc_zc_execute_t);
req_coroipcc_zc_execute.header.id = ZC_EXECUTE_HEADER;
req_coroipcc_zc_execute.server_address = hdr->server_address;
iovec.iov_base = &req_coroipcc_zc_execute;
iovec.iov_len = sizeof (mar_req_coroipcc_zc_execute_t);
res = coroipcc_msg_send_reply_receive (
ipc_context,
&iovec,
1,
res_msg,
res_len);
return (res);
}
-
+
cs_error_t
saHandleCreate (
struct saHandleDatabase *handleDatabase,
int instanceSize,
uint64_t *handleOut)
{
uint32_t handle;
uint32_t check;
void *newHandles = NULL;
int found = 0;
void *instance;
int i;
hdb_lock (handleDatabase);
for (handle = 0; handle < handleDatabase->handleCount; handle++) {
if (handleDatabase->handles[handle].state == SA_HANDLE_STATE_EMPTY) {
found = 1;
break;
}
}
if (found == 0) {
handleDatabase->handleCount += 1;
newHandles = (struct saHandle *)realloc (handleDatabase->handles,
sizeof (struct saHandle) * handleDatabase->handleCount);
if (newHandles == NULL) {
hdb_unlock (handleDatabase);
return (CS_ERR_NO_MEMORY);
}
handleDatabase->handles = newHandles;
}
instance = malloc (instanceSize);
if (instance == 0) {
free (newHandles);
hdb_unlock (handleDatabase);
return (CS_ERR_NO_MEMORY);
}
/*
* This code makes sure the random number isn't zero
* We use 0 to specify an invalid handle out of the 1^64 address space
* If we get 0 200 times in a row, the RNG may be broken
*/
for (i = 0; i < 200; i++) {
check = random();
if (check != 0) {
break;
}
}
memset (instance, 0, instanceSize);
handleDatabase->handles[handle].state = SA_HANDLE_STATE_ACTIVE;
handleDatabase->handles[handle].instance = instance;
handleDatabase->handles[handle].refCount = 1;
handleDatabase->handles[handle].check = check;
*handleOut = (uint64_t)((uint64_t)check << 32 | handle);
hdb_unlock (handleDatabase);
return (CS_OK);
}
cs_error_t
saHandleDestroy (
struct saHandleDatabase *handleDatabase,
uint64_t inHandle)
{
cs_error_t error = CS_OK;
uint32_t check = inHandle >> 32;
uint32_t handle = inHandle & 0xffffffff;
hdb_lock (handleDatabase);
if (check != handleDatabase->handles[handle].check) {
hdb_unlock (handleDatabase);
error = CS_ERR_BAD_HANDLE;
return (error);
}
handleDatabase->handles[handle].state = SA_HANDLE_STATE_PENDINGREMOVAL;
hdb_unlock (handleDatabase);
saHandleInstancePut (handleDatabase, inHandle);
return (error);
}
cs_error_t
saHandleInstanceGet (
struct saHandleDatabase *handleDatabase,
uint64_t inHandle,
void **instance)
-{
+{
uint32_t check = inHandle >> 32;
uint32_t handle = inHandle & 0xffffffff;
cs_error_t error = CS_OK;
hdb_lock (handleDatabase);
if (handle >= (uint64_t)handleDatabase->handleCount) {
error = CS_ERR_BAD_HANDLE;
goto error_exit;
}
if (handleDatabase->handles[handle].state != SA_HANDLE_STATE_ACTIVE) {
error = CS_ERR_BAD_HANDLE;
goto error_exit;
}
if (check != handleDatabase->handles[handle].check) {
error = CS_ERR_BAD_HANDLE;
goto error_exit;
}
*instance = handleDatabase->handles[handle].instance;
handleDatabase->handles[handle].refCount += 1;
error_exit:
hdb_unlock (handleDatabase);
return (error);
}
cs_error_t
saHandleInstancePut (
struct saHandleDatabase *handleDatabase,
uint64_t inHandle)
{
void *instance;
cs_error_t error = CS_OK;
uint32_t check = inHandle >> 32;
uint32_t handle = inHandle & 0xffffffff;
hdb_lock (handleDatabase);
if (check != handleDatabase->handles[handle].check) {
error = CS_ERR_BAD_HANDLE;
goto error_exit;
}
handleDatabase->handles[handle].refCount -= 1;
assert (handleDatabase->handles[handle].refCount >= 0);
if (handleDatabase->handles[handle].refCount == 0) {
instance = (handleDatabase->handles[handle].instance);
handleDatabase->handleInstanceDestructor (instance);
free (instance);
memset (&handleDatabase->handles[handle], 0, sizeof (struct saHandle));
}
error_exit:
hdb_unlock (handleDatabase);
return (error);
}
diff --git a/lib/evs.c b/lib/evs.c
index 32dbfc3e..326c417f 100644
--- a/lib/evs.c
+++ b/lib/evs.c
@@ -1,571 +1,571 @@
/*
* vi: set autoindent tabstop=4 shiftwidth=4 :
* Copyright (c) 2004-2005 MontaVista Software, Inc.
* Copyright (c) 2006-2007, 2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Provides an extended virtual synchrony API using the corosync executive
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <corosync/totem/totem.h>
#include <corosync/corotypes.h>
#include <corosync/evs.h>
#include <corosync/ipc_evs.h>
#include <corosync/coroipcc.h>
#undef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
struct evs_inst {
void *ipc_ctx;
int finalize;
evs_callbacks_t callbacks;
pthread_mutex_t response_mutex;
pthread_mutex_t dispatch_mutex;
};
static void evs_instance_destructor (void *instance);
DECLARE_SAHDB_DATABASE (evs_handle_t_db, evs_instance_destructor);
/*
* Clean up function for an evt instance (saEvtInitialize) handle
*/
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);
}
/**
* @defgroup evs_coroipcc The extended virtual synchrony passthrough API
* @ingroup coroipcc
*
* @{
*/
/**
* test
* @param handle The handle of evs initialize
* @param callbacks The callbacks for evs_initialize
* @returns EVS_OK
*/
evs_error_t evs_initialize (
evs_handle_t *handle,
evs_callbacks_t *callbacks)
{
cs_error_t error;
struct evs_inst *evs_inst;
error = saHandleCreate (&evs_handle_t_db, sizeof (struct evs_inst), handle);
if (error != CS_OK) {
goto error_no_destroy;
}
error = saHandleInstanceGet (&evs_handle_t_db, *handle, (void *)&evs_inst);
if (error != CS_OK) {
goto error_destroy;
}
error = coroipcc_service_connect (
IPC_SOCKET_NAME,
EVS_SERVICE,
IPC_REQUEST_SIZE,
IPC_RESPONSE_SIZE,
IPC_DISPATCH_SIZE,
&evs_inst->ipc_ctx);
if (error != EVS_OK) {
goto error_put_destroy;
}
memcpy (&evs_inst->callbacks, callbacks, sizeof (evs_callbacks_t));
pthread_mutex_init (&evs_inst->response_mutex, NULL);
pthread_mutex_init (&evs_inst->dispatch_mutex, NULL);
saHandleInstancePut (&evs_handle_t_db, *handle);
return (CS_OK);
error_put_destroy:
saHandleInstancePut (&evs_handle_t_db, *handle);
error_destroy:
saHandleDestroy (&evs_handle_t_db, *handle);
error_no_destroy:
return (error);
}
evs_error_t evs_finalize (
evs_handle_t handle)
{
struct evs_inst *evs_inst;
cs_error_t error;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
pthread_mutex_lock (&evs_inst->response_mutex);
/*
* Another thread has already started finalizing
*/
if (evs_inst->finalize) {
pthread_mutex_unlock (&evs_inst->response_mutex);
saHandleInstancePut (&evs_handle_t_db, handle);
return (EVS_ERR_BAD_HANDLE);
}
evs_inst->finalize = 1;
coroipcc_service_disconnect (evs_inst->ipc_ctx);
pthread_mutex_unlock (&evs_inst->response_mutex);
saHandleDestroy (&evs_handle_t_db, handle);
saHandleInstancePut (&evs_handle_t_db, handle);
return (EVS_OK);
}
evs_error_t evs_fd_get (
evs_handle_t handle,
int *fd)
{
cs_error_t error;
struct evs_inst *evs_inst;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
*fd = coroipcc_fd_get (evs_inst->ipc_ctx);
saHandleInstancePut (&evs_handle_t_db, handle);
return (CS_OK);
}
evs_error_t evs_dispatch (
evs_handle_t handle,
cs_dispatch_flags_t dispatch_types)
{
int timeout = -1;
cs_error_t error;
int cont = 1; /* always continue do loop except when set to 0 */
int dispatch_avail;
struct evs_inst *evs_inst;
struct res_evs_confchg_callback *res_evs_confchg_callback;
struct res_evs_deliver_callback *res_evs_deliver_callback;
evs_callbacks_t callbacks;
mar_res_header_t *dispatch_data;
int ignore_dispatch = 0;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
/*
* Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and
* wait indefinately for SA_DISPATCH_BLOCKING
*/
if (dispatch_types == EVS_DISPATCH_ALL) {
timeout = 0;
}
do {
pthread_mutex_lock (&evs_inst->dispatch_mutex);
dispatch_avail = coroipcc_dispatch_get (
evs_inst->ipc_ctx,
(void **)&dispatch_data,
timeout);
pthread_mutex_unlock (&evs_inst->dispatch_mutex);
if (dispatch_avail == 0 && dispatch_types == EVS_DISPATCH_ALL) {
break; /* exit do while cont is 1 loop */
- } else
+ } else
if (dispatch_avail == 0) {
continue; /* next dispatch event */
}
if (dispatch_avail == -1) {
if (evs_inst->finalize == 1) {
error = CS_OK;
} else {
error = CS_ERR_LIBRARY;
}
goto error_put;
}
/*
* Make copy of callbacks, message data, unlock instance, and call callback
* A risk of this dispatch method is that the callback routines may
* operate at the same time that evsFinalize has been called.
*/
memcpy (&callbacks, &evs_inst->callbacks, sizeof (evs_callbacks_t));
/*
* Dispatch incoming message
*/
switch (dispatch_data->id) {
case MESSAGE_RES_EVS_DELIVER_CALLBACK:
res_evs_deliver_callback = (struct res_evs_deliver_callback *)dispatch_data;
callbacks.evs_deliver_fn (
res_evs_deliver_callback->local_nodeid,
&res_evs_deliver_callback->msg,
res_evs_deliver_callback->msglen);
break;
case MESSAGE_RES_EVS_CONFCHG_CALLBACK:
res_evs_confchg_callback = (struct res_evs_confchg_callback *)dispatch_data;
callbacks.evs_confchg_fn (
res_evs_confchg_callback->member_list,
res_evs_confchg_callback->member_list_entries,
res_evs_confchg_callback->left_list,
res_evs_confchg_callback->left_list_entries,
res_evs_confchg_callback->joined_list,
res_evs_confchg_callback->joined_list_entries);
break;
default:
coroipcc_dispatch_put (evs_inst->ipc_ctx);
error = CS_ERR_LIBRARY;
goto error_put;
break;
}
coroipcc_dispatch_put (evs_inst->ipc_ctx);
/*
* Determine if more messages should be processed
* */
switch (dispatch_types) {
case EVS_DISPATCH_ONE:
if (ignore_dispatch) {
ignore_dispatch = 0;
} else {
cont = 0;
}
break;
case EVS_DISPATCH_ALL:
if (ignore_dispatch) {
ignore_dispatch = 0;
}
break;
case EVS_DISPATCH_BLOCKING:
break;
}
} while (cont);
error_put:
saHandleInstancePut (&evs_handle_t_db, handle);
return (error);
}
evs_error_t evs_join (
evs_handle_t handle,
const struct evs_group *groups,
size_t group_entries)
{
evs_error_t error;
struct evs_inst *evs_inst;
struct iovec iov[2];
struct req_lib_evs_join req_lib_evs_join;
struct res_lib_evs_join res_lib_evs_join;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != EVS_OK) {
return (error);
}
- req_lib_evs_join.header.size = sizeof (struct req_lib_evs_join) +
+ req_lib_evs_join.header.size = sizeof (struct req_lib_evs_join) +
(group_entries * sizeof (struct evs_group));
req_lib_evs_join.header.id = MESSAGE_REQ_EVS_JOIN;
req_lib_evs_join.group_entries = group_entries;
iov[0].iov_base = &req_lib_evs_join;
iov[0].iov_len = sizeof (struct req_lib_evs_join);
iov[1].iov_base = (void*) groups; /* cast away const */
iov[1].iov_len = (group_entries * sizeof (struct evs_group));
-
+
pthread_mutex_lock (&evs_inst->response_mutex);
error = coroipcc_msg_send_reply_receive (evs_inst->ipc_ctx, iov, 2,
&res_lib_evs_join, sizeof (struct res_lib_evs_join));
pthread_mutex_unlock (&evs_inst->response_mutex);
if (error != CS_OK) {
goto error_exit;
}
error = res_lib_evs_join.header.error;
error_exit:
saHandleInstancePut (&evs_handle_t_db, handle);
return (error);
}
evs_error_t evs_leave (
evs_handle_t handle,
const struct evs_group *groups,
size_t group_entries)
{
evs_error_t error;
struct evs_inst *evs_inst;
struct iovec iov[2];
struct req_lib_evs_leave req_lib_evs_leave;
struct res_lib_evs_leave res_lib_evs_leave;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
- req_lib_evs_leave.header.size = sizeof (struct req_lib_evs_leave) +
+ req_lib_evs_leave.header.size = sizeof (struct req_lib_evs_leave) +
(group_entries * sizeof (struct evs_group));
req_lib_evs_leave.header.id = MESSAGE_REQ_EVS_LEAVE;
req_lib_evs_leave.group_entries = group_entries;
iov[0].iov_base = &req_lib_evs_leave;
iov[0].iov_len = sizeof (struct req_lib_evs_leave);
iov[1].iov_base = (void *) groups; /* cast away const */
iov[1].iov_len = (group_entries * sizeof (struct evs_group));
-
+
pthread_mutex_lock (&evs_inst->response_mutex);
error = coroipcc_msg_send_reply_receive (evs_inst->ipc_ctx, iov, 2,
&res_lib_evs_leave, sizeof (struct res_lib_evs_leave));
pthread_mutex_unlock (&evs_inst->response_mutex);
if (error != CS_OK) {
goto error_exit;
}
error = res_lib_evs_leave.header.error;
error_exit:
saHandleInstancePut (&evs_handle_t_db, handle);
return (error);
}
evs_error_t evs_mcast_joined (
evs_handle_t handle,
evs_guarantee_t guarantee,
const struct iovec *iovec,
unsigned int iov_len)
{
int i;
evs_error_t error;
struct evs_inst *evs_inst;
struct iovec iov[64];
struct req_lib_evs_mcast_joined req_lib_evs_mcast_joined;
struct res_lib_evs_mcast_joined res_lib_evs_mcast_joined;
size_t msg_len = 0;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
for (i = 0; i < iov_len; i++ ) {
msg_len += iovec[i].iov_len;
}
req_lib_evs_mcast_joined.header.size = sizeof (struct req_lib_evs_mcast_joined) +
msg_len;
req_lib_evs_mcast_joined.header.id = MESSAGE_REQ_EVS_MCAST_JOINED;
req_lib_evs_mcast_joined.guarantee = guarantee;
req_lib_evs_mcast_joined.msg_len = msg_len;
iov[0].iov_base = &req_lib_evs_mcast_joined;
iov[0].iov_len = sizeof (struct req_lib_evs_mcast_joined);
memcpy (&iov[1], iovec, iov_len * sizeof (struct iovec));
-
+
pthread_mutex_lock (&evs_inst->response_mutex);
error = coroipcc_msg_send_reply_receive (evs_inst->ipc_ctx, iov,
iov_len + 1,
&res_lib_evs_mcast_joined,
sizeof (struct res_lib_evs_mcast_joined));
pthread_mutex_unlock (&evs_inst->response_mutex);
if (error != CS_OK) {
goto error_exit;
}
error = res_lib_evs_mcast_joined.header.error;
error_exit:
saHandleInstancePut (&evs_handle_t_db, handle);
return (error);
}
evs_error_t evs_mcast_groups (
evs_handle_t handle,
evs_guarantee_t guarantee,
const struct evs_group *groups,
size_t group_entries,
const struct iovec *iovec,
unsigned int iov_len)
{
int i;
evs_error_t error;
struct evs_inst *evs_inst;
struct iovec iov[64]; /* FIXME: what if iov_len > 62 ? use malloc */
struct req_lib_evs_mcast_groups req_lib_evs_mcast_groups;
struct res_lib_evs_mcast_groups res_lib_evs_mcast_groups;
size_t msg_len = 0;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
for (i = 0; i < iov_len; i++) {
msg_len += iovec[i].iov_len;
}
- req_lib_evs_mcast_groups.header.size = sizeof (struct req_lib_evs_mcast_groups) +
+ req_lib_evs_mcast_groups.header.size = sizeof (struct req_lib_evs_mcast_groups) +
(group_entries * sizeof (struct evs_group)) + msg_len;
req_lib_evs_mcast_groups.header.id = MESSAGE_REQ_EVS_MCAST_GROUPS;
req_lib_evs_mcast_groups.guarantee = guarantee;
req_lib_evs_mcast_groups.msg_len = msg_len;
req_lib_evs_mcast_groups.group_entries = group_entries;
iov[0].iov_base = &req_lib_evs_mcast_groups;
iov[0].iov_len = sizeof (struct req_lib_evs_mcast_groups);
iov[1].iov_base = (void *) groups; /* cast away const */
iov[1].iov_len = (group_entries * sizeof (struct evs_group));
memcpy (&iov[2], iovec, iov_len * sizeof (struct iovec));
-
+
pthread_mutex_lock (&evs_inst->response_mutex);
error = coroipcc_msg_send_reply_receive (evs_inst->ipc_ctx, iov,
iov_len + 2,
&res_lib_evs_mcast_groups,
sizeof (struct res_lib_evs_mcast_groups));
pthread_mutex_unlock (&evs_inst->response_mutex);
if (error != CS_OK) {
goto error_exit;
}
error = res_lib_evs_mcast_groups.header.error;
error_exit:
saHandleInstancePut (&evs_handle_t_db, handle);
return (error);
}
evs_error_t evs_membership_get (
evs_handle_t handle,
unsigned int *local_nodeid,
unsigned int *member_list,
size_t *member_list_entries)
{
evs_error_t error;
struct evs_inst *evs_inst;
struct iovec iov;
struct req_lib_evs_membership_get req_lib_evs_membership_get;
struct res_lib_evs_membership_get res_lib_evs_membership_get;
error = saHandleInstanceGet (&evs_handle_t_db, handle, (void *)&evs_inst);
if (error != CS_OK) {
return (error);
}
req_lib_evs_membership_get.header.size = sizeof (struct req_lib_evs_membership_get);
req_lib_evs_membership_get.header.id = MESSAGE_REQ_EVS_MEMBERSHIP_GET;
iov.iov_base = &req_lib_evs_membership_get;
iov.iov_len = sizeof (struct req_lib_evs_membership_get);
pthread_mutex_lock (&evs_inst->response_mutex);
error = coroipcc_msg_send_reply_receive (evs_inst->ipc_ctx,
&iov,
1,
&res_lib_evs_membership_get,
sizeof (struct res_lib_evs_membership_get));
pthread_mutex_unlock (&evs_inst->response_mutex);
if (error != CS_OK) {
goto error_exit;
}
error = res_lib_evs_membership_get.header.error;
/*
* Copy results to caller
*/
if (local_nodeid) {
*local_nodeid = res_lib_evs_membership_get.local_nodeid;
}
*member_list_entries = MIN (*member_list_entries,
res_lib_evs_membership_get.member_list_entries);
if (member_list) {
- memcpy (member_list, &res_lib_evs_membership_get.member_list,
+ memcpy (member_list, &res_lib_evs_membership_get.member_list,
*member_list_entries * sizeof (struct in_addr));
}
error_exit:
saHandleInstancePut (&evs_handle_t_db, handle);
return (error);
}
/** @} */
diff --git a/lib/libcfg.versions b/lib/libcfg.versions
index 1549d767..3a49d820 100644
--- a/lib/libcfg.versions
+++ b/lib/libcfg.versions
@@ -1,34 +1,34 @@
# Version and symbol export for libcfg.so
COROSYNC_CFG_0.82 {
global:
corosync_cfg_initialize;
corosync_cfg_fd_get;
corosync_cfg_dispatch;
corosync_cfg_finalize;
corosync_cfg_administrative_state_get;
corosync_cfg_administrative_state_set;
corosync_cfg_track;
corosync_cfg_track_stop;
corosync_cfg_ring_status_get;
corosync_cfg_ring_reenable;
corosync_cfg_service_load;
corosync_cfg_service_unload;
-
-
+
+
local:
coroipcc_service_connect;
coroipcc_service_disconnect;
coroipcc_dispatch_flow_control_get;
coroipcc_fd_get;
coroipcc_dispatch_recv;
coroipcc_msg_send_reply_receive;
coroipcc_msg_send_reply_receive_in_buf;
coroipcc_zcb_alloc;
coroipcc_zcb_free;
coroipcc_zcb_msg_send_reply_receive;
saHandleCreate;
saHandleDestroy;
saHandleInstanceGet;
saHandleInstancePut;
};
diff --git a/lib/libquorum.versions b/lib/libquorum.versions
index 76e22406..4a7cb341 100644
--- a/lib/libquorum.versions
+++ b/lib/libquorum.versions
@@ -1,27 +1,27 @@
# Version and symbol export for libquorum.so
COROSYNC_QUORUM_1.0 {
- global:
+ global:
quorum_initialize;
quorum_finalize;
quorum_getquorate;
quorum_initialize;
quorum_finalize;
quorum_dispatch;
local:
coroipcc_service_connect;
coroipcc_service_disconnect;
coroipcc_dispatch_flow_control_get;
coroipcc_fd_get;
coroipcc_dispatch_recv;
coroipcc_msg_send_reply_receive;
coroipcc_msg_send_reply_receive_in_buf;
coroipcc_zcb_alloc;
coroipcc_zcb_free;
coroipcc_zcb_msg_send_reply_receive;
saHandleCreate;
saHandleDestroy;
saHandleInstanceGet;
saHandleInstancePut;
};
diff --git a/lib/libvotequorum.versions b/lib/libvotequorum.versions
index 101a039c..bba4c4bd 100644
--- a/lib/libvotequorum.versions
+++ b/lib/libvotequorum.versions
@@ -1,36 +1,36 @@
# Version and symbol export for libvotequorum.so
COROSYNC_VOTEQUORUM_1.0 {
- global:
+ global:
votequorum_initialize;
votequorum_finalize;
votequorum_getinfo;
votequorum_setexpected;
votequorum_setvotes;
votequorum_qdisk_register;
votequorum_qdisk_unregister;
votequorum_qdisk_poll;
votequorum_qdisk_getinfo;
votequorum_setstate;
votequorum_leaving;
votequorum_trackstart;
votequorum_trackstop;
votequorum_context_get;
votequorum_context_set;
local:
coroipcc_service_connect;
coroipcc_service_disconnect;
coroipcc_dispatch_flow_control_get;
coroipcc_fd_get;
coroipcc_dispatch_recv;
coroipcc_msg_send_reply_receive;
coroipcc_msg_send_reply_receive_in_buf;
coroipcc_zcb_alloc;
coroipcc_zcb_free;
coroipcc_zcb_msg_send_reply_receive;
saHandleCreate;
saHandleDestroy;
saHandleInstanceGet;
saHandleInstancePut;
};
diff --git a/lib/pload.c b/lib/pload.c
index b04eb949..82474b5b 100644
--- a/lib/pload.c
+++ b/lib/pload.c
@@ -1,233 +1,233 @@
/*
* Copyright (c) 2008-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <corosync/swab.h>
#include <corosync/totem/totem.h>
#include <corosync/corotypes.h>
#include <corosync/ipc_pload.h>
#include <corosync/pload.h>
#include <corosync/coroipcc.h>
static void pload_instance_destructor (void *instance);
struct pload_inst {
void *ipc_ctx;
pthread_mutex_t response_mutex;
pthread_mutex_t dispatch_mutex;
unsigned int finalize;
};
DECLARE_SAHDB_DATABASE(pload_handle_t_db,pload_instance_destructor);
/*
* Clean up function for an evt instance (saEvtInitialize) handle
*/
static void pload_instance_destructor (void *instance)
{
struct pload_inst *pload_inst = instance;
pthread_mutex_destroy (&pload_inst->response_mutex);
pthread_mutex_destroy (&pload_inst->dispatch_mutex);
}
/**
* @defgroup pload_corosync The extended virtual synchrony passthrough API
* @ingroup corosync
*
* @{
*/
/**
* test
* @param handle The handle of pload initialize
* @param callbacks The callbacks for pload_initialize
* @returns PLOAD_OK
*/
unsigned int pload_initialize (
pload_handle_t *handle,
pload_callbacks_t *callbacks)
{
cs_error_t error;
struct pload_inst *pload_inst;
error = saHandleCreate (&pload_handle_t_db, sizeof (struct pload_inst), handle);
if (error != CS_OK) {
goto error_no_destroy;
}
error = saHandleInstanceGet (&pload_handle_t_db, *handle, (void *)&pload_inst);
if (error != CS_OK) {
goto error_destroy;
}
error = coroipcc_service_connect (
IPC_SOCKET_NAME,
PLOAD_SERVICE,
IPC_REQUEST_SIZE,
IPC_RESPONSE_SIZE,
IPC_DISPATCH_SIZE,
&pload_inst->ipc_ctx);
if (error != CS_OK) {
goto error_put_destroy;
}
pthread_mutex_init (&pload_inst->response_mutex, NULL);
pthread_mutex_init (&pload_inst->dispatch_mutex, NULL);
(void)saHandleInstancePut (&pload_handle_t_db, *handle);
return (CS_OK);
error_put_destroy:
(void)saHandleInstancePut (&pload_handle_t_db, *handle);
error_destroy:
(void)saHandleDestroy (&pload_handle_t_db, *handle);
error_no_destroy:
return (error);
}
unsigned int pload_finalize (
pload_handle_t handle)
{
struct pload_inst *pload_inst;
cs_error_t error;
error = saHandleInstanceGet (&pload_handle_t_db, handle, (void *)&pload_inst);
if (error != CS_OK) {
return (error);
}
pthread_mutex_lock (&pload_inst->response_mutex);
/*
* Another thread has already started finalizing
*/
if (pload_inst->finalize) {
pthread_mutex_unlock (&pload_inst->response_mutex);
(void)saHandleInstancePut (&pload_handle_t_db, handle);
return (PLOAD_ERR_BAD_HANDLE);
}
pload_inst->finalize = 1;
coroipcc_service_disconnect(pload_inst->ipc_ctx);
pthread_mutex_unlock (&pload_inst->response_mutex);
(void)saHandleDestroy (&pload_handle_t_db, handle);
(void)saHandleInstancePut (&pload_handle_t_db, handle);
return (PLOAD_OK);
}
unsigned int pload_fd_get (
pload_handle_t handle,
int *fd)
{
cs_error_t error;
struct pload_inst *pload_inst;
error = saHandleInstanceGet (&pload_handle_t_db, handle, (void *)&pload_inst);
if (error != CS_OK) {
return (error);
}
- *fd = coroipcc_fd_get (pload_inst->ipc_ctx);
+ *fd = coroipcc_fd_get (pload_inst->ipc_ctx);
(void)saHandleInstancePut (&pload_handle_t_db, handle);
return (CS_OK);
}
unsigned int pload_start (
pload_handle_t handle,
unsigned int code,
unsigned int msg_count,
unsigned int msg_size)
{
unsigned int error;
struct pload_inst *pload_inst;
struct iovec iov;
struct req_lib_pload_start req_lib_pload_start;
struct res_lib_pload_start res_lib_pload_start;
error = saHandleInstanceGet (&pload_handle_t_db, handle, (void *)&pload_inst);
if (error != CS_OK) {
return (error);
}
req_lib_pload_start.header.size = sizeof (struct req_lib_pload_start);
req_lib_pload_start.header.id = MESSAGE_REQ_PLOAD_START;
req_lib_pload_start.msg_code = code;
req_lib_pload_start.msg_count = msg_count;
req_lib_pload_start.msg_size = msg_size;
iov.iov_base = (char *)&req_lib_pload_start;
iov.iov_len = sizeof (struct req_lib_pload_start);
-
+
pthread_mutex_lock (&pload_inst->response_mutex);
error = coroipcc_msg_send_reply_receive(pload_inst->ipc_ctx,
&iov,
1,
&res_lib_pload_start,
sizeof (struct res_lib_pload_start));
pthread_mutex_unlock (&pload_inst->response_mutex);
if (error != CS_OK) {
goto error_exit;
}
error = res_lib_pload_start.header.error;
error_exit:
(void)saHandleInstancePut (&pload_handle_t_db, handle);
return (error);
}
/** @} */
diff --git a/lib/util.h b/lib/util.h
index 63a1bf30..a3b948d3 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -1,151 +1,151 @@
/*
* Copyright (c) 2002-2003 MontaVista Software, 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.
*/
#ifndef AIS_UTIL_H_DEFINED
#define AIS_UTIL_H_DEFINED
#include <pthread.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include "../include/ipc_gen.h"
/* Debug macro
*/
#ifdef DEBUG
#define DPRINT(s) printf s
#else
#define DPRINT(s)
#endif
-
+
#ifdef SO_NOSIGPIPE
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
void socket_nosigpipe(int s);
#else
#define socket_nosigpipe(s)
#endif
struct saHandleDatabase {
unsigned int handleCount;
struct saHandle *handles;
pthread_mutex_t mutex;
void (*handleInstanceDestructor) (void *);
};
struct saVersionDatabase {
int versionCount;
SaVersionT *versionsSupported;
};
cs_error_t
saServiceConnect (
int *responseOut,
int *callbackOut,
enum service_types service);
cs_error_t
saRecvRetry (
int s,
void *msg,
size_t len);
cs_error_t
saSendRetry (
int s,
const void *msg,
size_t len);
cs_error_t saSendMsgRetry (
int s,
struct iovec *iov,
unsigned int iov_len);
cs_error_t saSendMsgReceiveReply (
int s,
struct iovec *iov,
unsigned int iov_len,
void *responseMessage,
int responseLen);
cs_error_t saSendReceiveReply (
int s,
void *requestMessage,
int requestLen,
void *responseMessage,
int responseLen);
cs_error_t
saPollRetry (
struct pollfd *ufds,
unsigned int nfds,
int timeout);
cs_error_t
saHandleCreate (
struct saHandleDatabase *handleDatabase,
int instanceSize,
SaUint64T *handleOut);
cs_error_t
saHandleDestroy (
struct saHandleDatabase *handleDatabase,
SaUint64T handle);
cs_error_t
saHandleInstanceGet (
struct saHandleDatabase *handleDatabase,
SaUint64T handle,
void **instance);
cs_error_t
saHandleInstancePut (
struct saHandleDatabase *handleDatabase,
SaUint64T handle);
cs_error_t
saVersionVerify (
struct saVersionDatabase *versionDatabase,
SaVersionT *version);
#define offset_of(type,member) (int)(&(((type *)0)->member))
SaTimeT
clustTimeNow(void);
#endif /* AIS_UTIL_H_DEFINED */
diff --git a/man/Makefile.am b/man/Makefile.am
index c1c9ce3d..685feda4 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -1,120 +1,120 @@
# Copyright (c) 2004 MontaVista Software, Inc.
# Copyright (c) 2009 Red Hat, Inc.
#
# Authors: Steven Dake (sdake@redhat.com)
# Fabio M. Di Nitto (fdinitto@redhat.com)
-#
+#
# All rights reserved.
-#
+#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = index.html
dist_man_MANS = \
corosync.conf.5 \
confdb_overview.8 \
corosync-objctl.8 \
corosync_overview.8 \
cpg_overview.8 \
evs_overview.8 \
logsys_overview.8 \
votequorum_overview.8 \
coroipc_overview.8 \
confdb_dispatch.3 \
confdb_fd_get.3 \
confdb_finalize.3 \
confdb_initialize.3 \
confdb_key_create.3 \
confdb_key_delete.3 \
confdb_key_iter.3 \
confdb_key_replace.3 \
confdb_object_create.3 \
confdb_object_destroy.3 \
confdb_object_find.3 \
confdb_object_iter.3 \
confdb_object_parent_get.3 \
cpg_context_get.3 \
cpg_context_set.3 \
cpg_dispatch.3 \
cpg_fd_get.3 \
cpg_finalize.3 \
cpg_initialize.3 \
cpg_join.3 \
cpg_leave.3 \
cpg_local_get.3 \
cpg_mcast_joined.3 \
cpg_zcb_mcast_joined.3 \
cpg_zcb_alloc.3 \
cpg_zcb_free.3 \
cpg_membership_get.3 \
evs_dispatch.3 \
evs_fd_get.3 \
evs_finalize.3 \
evs_initialize.3 \
evs_join.3 \
evs_leave.3 \
evs_mcast_groups.3 \
evs_mcast_joined.3 \
evs_membership_get.3 \
votequorum_dispatch.3 \
votequorum_fd_get.3 \
votequorum_finalize.3 \
votequorum_getinfo.3 \
votequorum_initialize.3 \
votequorum_leaving.3 \
votequorum_qdisk_getinfo.3 \
votequorum_qdisk_poll.3 \
votequorum_qdisk_register.3 \
votequorum_qdisk_unregister.3 \
votequorum_setexpected.3 \
votequorum_setvotes.3
if BUILD_HTML_DOCS
HTML_DOCS = $(dist_man_MANS:%=%.html)
INDEX_HTML = index.html
%.html: %
$(GROFF) -mandoc -Thtml $^ > $@
install-data-local:
install -d $(DESTDIR)/${docdir}/html
install -m644 ${srcdir}/$(INDEX_HTML) $(HTML_DOCS) $(DESTDIR)/${docdir}/html/
uninstall-local:
cd $(DESTDIR)/${docdir}/html && rm -f $(INDEX_HTML) $(HTML_DOCS)
rmdir $(DESTDIR)/${docdir}/html 2> /dev/null || :
all-local: $(HTML_DOCS)
clean-local:
rm -rf $(HTML_DOCS)
endif
diff --git a/man/confdb_dispatch.3 b/man/confdb_dispatch.3
index b8491e54..748bc2c4 100644
--- a/man/confdb_dispatch.3
+++ b/man/confdb_dispatch.3
@@ -1,109 +1,109 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_DISPATCH 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_dispatch \- Dispatches callbacks from the CONFDB service
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "int confdb_dispatch(confdb_handle_t " handle ", confdb_dispatch_t *" dispatch_types ");"
.SH DESCRIPTION
The
.B confdb_dispatch
function is used to dispatch configuration changes.
.PP
Each application may have several connections to the CONFDB API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection.
.PP
The
.I dispatch_types
argument is used to identify the type of dispatch to execute. The possible types are
defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
CONFDB_DISPATCH_ONE,
CONFDB_DISPATCH_ALL,
CONFDB_DISPATCH_BLOCKING
} confdb_dispatch_t;
.ta
.fi
.RE
.IP
.PP
.PP
The dispatch values have the following meanings:
.TP
.B CONFDB_DISPATCH_ONE
Dispatch at least one callback, blocking until the callback is dispatched.
.TP
.B CONFDB_DISPATCH_ALL
Dispatch all waiting callbacks without blocking to wait for any callbacks.
.TP
.B CONFDB_DISPATCH_BLOCKING
Dispatch all callbacks blocking indefinitely. This is used in a threaded
program where a thread is created, and then confdb_dispatch() is called immediately
from the created thread to execute callbacks.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_fd_get (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_fd_get.3 b/man/confdb_fd_get.3
index 0b826db5..c9e88834 100644
--- a/man/confdb_fd_get.3
+++ b/man/confdb_fd_get.3
@@ -1,77 +1,77 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_FD_GET 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_fd_get \- Dispatches callbacks from the CONFDB service
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "int confdb_fd_get(confdb_handle_t " handle ", int *" fd ");"
.SH DESCRIPTION
The
.B confdb_fd_get
function is used to retrieve the file descriptor that may be used with the poll
system call to determine when
.B confdb_dispatch(3)
won't block. The
.I handle
argument may not be used directly with
.B poll
because it is not the file descriptor, but instead an internal identifier used
by the CONFDB library.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_fd_get (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_finalize.3 b/man/confdb_finalize.3
index d6cf46eb..2246cb4c 100644
--- a/man/confdb_finalize.3
+++ b/man/confdb_finalize.3
@@ -1,74 +1,74 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_FINALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_finalize \- Terminate a connection to the CONFDB service
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "int confdb_finalize(confdb_handle_t " handle ");"
.SH DESCRIPTION
The
.B confdb_finalize
function is used to close a connection to the configuration dabatase API.
Once the connection is finalized, the handle may not be used again by applications.
No more callbacks will be dispatched from the
.B confdb_dispatch function.
.PP
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_fd_get (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_initialize.3 b/man/confdb_initialize.3
index 9099a791..14541c86 100644
--- a/man/confdb_initialize.3
+++ b/man/confdb_initialize.3
@@ -1,115 +1,115 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_INITIALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_initialize \- Create a new connection to the ConfDb service
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "int confdb_initialize(confdb_handle_t *" handle ", confdb_callbacks_t *" callbacks ");
.SH DESCRIPTION
The
.B confdb_initialize
function is used to initialize a connection to the configuration database API.
.PP
Each application may have several connections to the CONFDB API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection. The
.I handle
argument is then used in other function calls to identify the connection to be used
for communication with the CONFDB service.
.PP
Every time the configuration database is updated, the callback is called.
The callback function is described by the following type definitions:
.PP
.PP
.IP
.RS
.ne 18
.nf
.ta 4n 20n 32n
typedef void (*confdb_change_notify_fn_t) (
confdb_handle_t handle,
unsigned int parent_object_handle,
unsigned int object_handle,
void *object_name,
int object_name_len,
void *key_name,
int key_name_len,
void *key_value,
int key_value_len);
.ta
.fi
.RE
.IP
.PP
.PP
The
.I callbacks
argument is of the type:
.IP
.RS
.ne 18
.nf
.PP
typedef struct {
confdb_change_notify_fn_t confdb_change_notify_fn;
} confdb_callbacks_t;
.ta
.fi
.RE
.IP
.PP
When a configuration change occurs, the callback
is called from the
.B confdb_dispatch()
-function.
+function.
.PP
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH BUGS
Callbacks are not support at the moment.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_finalize (3),
.BR confdb_fd_get (3),
.BR confdb_dispatch (3),
.PP
diff --git a/man/confdb_key_create.3 b/man/confdb_key_create.3
index 05151c5f..afa7eeeb 100644
--- a/man/confdb_key_create.3
+++ b/man/confdb_key_create.3
@@ -1,86 +1,86 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_KEY_CREATE 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_key_create \- Add a new key/value pair to the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_key_create(confdb_handle_t " handle ",
.BI unsigned int " parent_object_handle ",
.BI void " *key_name ",
.Bi int " key_name_len ",
.BI void " *value ",
.BI int " value_len "); "
.SH DESCRIPTION
The
.B confdb_key_create
function adds a new key/value pair to the specified parent object. Parent objects may contain
many keys and also sub-objects. The names of keys are not required to be unique: if you
call
.B confdb_key_create
twice with the same parameters you will create two identical keys in the database.
.BR
The parent object should already exist in the database, it can be OBJECT_PARENT_HANDLE
(the top-level object) but this is not recommended.
.BR
Unlike objects, keys do not have handles, so you can't go directly to a non-unique key
without using the
.B confdb_key_iter
function.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_key_delete.3 b/man/confdb_key_delete.3
index 1aa6461e..06ecdb72 100644
--- a/man/confdb_key_delete.3
+++ b/man/confdb_key_delete.3
@@ -1,82 +1,82 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_KEY_DELETE 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_key_delete \- Delete a key/value pair from the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_key_delete(confdb_handle_t " handle ",
.BI unsigned int " parent_object_handle ",
.BI void " *key_name ",
.BI int " key_name_len ",
.BI void " *value ",
.BI int " value_len "); "
.SH DESCRIPTION
The
.B confdb_key_delete
function removes a key/value pair from the configuration database.
.br
You must specify both the key name and its value, this is because keys are not
unique in the database, so a value is not enough to uniqely identify a key belonging
to a particular parent object.
.BR
Strictly, even give the key name and value is not enough to uniquely identify a key,
If there are two (or more) keys with the same name and value, only the first will
be deleted.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_key_iter.3 b/man/confdb_key_iter.3
index 6ee3cfaf..cce1ed32 100644
--- a/man/confdb_key_iter.3
+++ b/man/confdb_key_iter.3
@@ -1,82 +1,82 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_KEY_ITER 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_key_iter \- Iterate through key/value pairs in the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_key_iter_start(confdb_handle_t " handle ", unsigned int " parent_object_handle " ); "
.sp
.BI "confdb_error_t confdb_key_iter(confdb_handle_t " handle ", unsigned int " parent_object_handle ", void " *key_name ", int " *key_name_len ", void " *value ", int " *value_len " ); "
.SH DESCRIPTION
The
.B confdb_key_iter
-function repeatedly returns all key/value pairs that are subobjects of the specified parent. You must call
+function repeatedly returns all key/value pairs that are subobjects of the specified parent. You must call
.B confdb_key_iter_start
first. This establishes a context for the parent object so that it knows where you are in the list. Then the next call to
.B confdb_key_iter
will return the first key/value in the list. Subsequent calls will return any remaining keys. The function returns CONFDB_ERR_ACCESS when the all of the matching keys have been seen.
.BR
-The library holds a seperate context for each parent object, so you can call confdb_key_iter() on several parent objects at the same time and they will not interfere. Nor will they interfere with
+The library holds a seperate context for each parent object, so you can call confdb_key_iter() on several parent objects at the same time and they will not interfere. Nor will they interfere with
.B confdb_object_find
or
.B confdb_object_iter
calls on the same parent object.
.BR
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_key_replace.3 b/man/confdb_key_replace.3
index 19371441..ef6e5c22 100644
--- a/man/confdb_key_replace.3
+++ b/man/confdb_key_replace.3
@@ -1,82 +1,82 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_KEY_REPLACE 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_key_replace \- Replace a key/value pair from the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_key_replace(confdb_handle_t " handle ", unsigned int " parent_object_handle ", void " *key_name ",
.BI int " key_name_len ",
.BI void " *old_value ",
.BI int " old_value_len ",
.BI void " *new_value ",
.BI int " new_value_len "); "
.SH DESCRIPTION
The
.B confdb_key_replace
function replaces the value of a key in the configuration database.
.br
You must specify both the key name and its value, this is because keys are not
unique in the database, so a value is not enough to uniqely identify a key belonging
to a particular parent object.
.BR
Strictly, even give the key name and value is not enough to uniquely identify a key,
-If there are two (or more) keys with the same name and value, only the first will have
+If there are two (or more) keys with the same name and value, only the first will have
its value changed .
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_object_create.3 b/man/confdb_object_create.3
index 021b2837..37f10917 100644
--- a/man/confdb_object_create.3
+++ b/man/confdb_object_create.3
@@ -1,89 +1,89 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_OBJECT_CREATE 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_object_create \- Create a new object in the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_object_create(confdb_handle_t " handle ", unsigned int " parent_object_handle ",
.BI void " *object_name ",
.BI int " object_name_len ",
.BI unsigned int " *object_handle "); "
.SH DESCRIPTION
The
.B confdb_object_create
function create a new object in the configuration database. Objects may contain other sub-objects or
keys with values.
.BR
On success the handle of the new object is returned in
.B object_handle.
This value should be used to refer to the object in future, eg when retrieving sub-keys or if the
object is destroyed.
.B parent_object_handle
-is the handle of the object that is the parent of the new object. This can be
+is the handle of the object that is the parent of the new object. This can be
.B OBJECT_PARENT_HANDLE
if the new object is to be a child of the top-level object.
.BR
-Object names are not required to be unique in the database. If you call
+Object names are not required to be unique in the database. If you call
.B confdb_object_create
twice with the same parameters you will create two different objects with the same name
but distinct object handles. You can iterate through similarly name objects using the
.B confdb_object_find
call.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_fd_get (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_object_destroy.3 b/man/confdb_object_destroy.3
index 52d14e9b..92754043 100644
--- a/man/confdb_object_destroy.3
+++ b/man/confdb_object_destroy.3
@@ -1,79 +1,79 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_* 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_object_destroy \- Remove an object from the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_destroy(confdb_handle_t " handle ", unsigned int " object_handle ");
.SH DESCRIPTION
The
-.B confdb_object_destroy
+.B confdb_object_destroy
call removes an object from the configuration database. It also remove all subkeys and all
-subobjects in the database, so be VERY CAREFUL!.
+subobjects in the database, so be VERY CAREFUL!.
.BR
-The input value
+The input value
.B object_handle
-is the handle of the object to remove, this can be got from the
+is the handle of the object to remove, this can be got from the
.B confdb_object_find
-or
+or
.B confdb_object_iter
-calls or
+calls or
.B confdb_object_create
calls.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_object_find.3 b/man/confdb_object_find.3
index b049f2ba..7afa937b 100644
--- a/man/confdb_object_find.3
+++ b/man/confdb_object_find.3
@@ -1,92 +1,92 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_OBJECT_FIND 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_object_find \- Find a named object in the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_object_find_start(confdb_handle_t " handle ", unsigned int " parent_object_handle " ); "
.sp
.BI "confdb_error_t confdb_object_find(confdb_handle_t " handle ", unsigned int " parent_object_handle ", void " *object_name ", int " object_name_len ", unsigned int " *object_handle " ); "
.sp
.BI "confdb_error_t confdb_object_find_destroy(confdb_handle_t " handle ", unsigned int " parent_object_handle " ); "
.SH DESCRIPTION
The
.B confdb_object_find
-function repeatedly returns objects that match a given name. You must call
+function repeatedly returns objects that match a given name. You must call
.B confdb_object_find_start
first. This establishes a context for the parent object so that it knows where you are in the list. Then the next call to
.B confdb_object_find
will return the handle of the first object that matches the passed in name. Subsequent calls will return any remaining objects
with the same name. The function returns CONFDB_ERR_ACCESS when the all of the matching objects have been seen.
.BR
-You need to provide the same object name and length for each call to
+You need to provide the same object name and length for each call to
.B confdb_object_find,
If you change either of then, the results are undefined.
.BR
-The library holds a seperate context for each parent object, so you can call confdb_object_iter() on several parent objects at the same time and they will not interfere. Nor will they interfere with
+The library holds a seperate context for each parent object, so you can call confdb_object_iter() on several parent objects at the same time and they will not interfere. Nor will they interfere with
.B confdb_object_iter
or
.B confdb_key_iter
calls on the same parent object.
.BR
-.B When you have finished searching for objects, call the
+.B When you have finished searching for objects, call the
.B confdb_object_find_destroy
library call to free up memory associated with the search context.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_object_iter.3 b/man/confdb_object_iter.3
index 9be7ee30..188d756c 100644
--- a/man/confdb_object_iter.3
+++ b/man/confdb_object_iter.3
@@ -1,84 +1,84 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_OBJECT_ITER 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_object_iter \- Iterate through objects in the Configuration Database
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_object_iter_start(confdb_handle_t " handle ", unsigned int " parent_object_handle " ); "
.sp
.BI "confdb_error_t confdb_object_iter(confdb_handle_t " handle ", unsigned int " parent_object_handle ", unsigned int " *object_handle ", void " *object_name ", int " *object_name_len " ); "
.sp
.BI "confdb_error_t confdb_object_iter_destroy(confdb_handle_t " handle ", unsigned int " parent_object_handle " ); "
.SH DESCRIPTION
The
.B confdb_object_iter
-function repeatedly returns all objects that are subobjects of the specified parent. You must call
+function repeatedly returns all objects that are subobjects of the specified parent. You must call
.B confdb_object_iter_start
first. This establishes a context for the parent object so that it knows where you are in the list. Then the next call to
.B confdb_object_iter
will return the handle of the first object in the list. Subsequent calls will return any remaining objects. The function returns CONFDB_ERR_ACCESS when the all of the matching objects have been seen. The function returns the name and length of the object as well
as its handle.
.BR
-.B When you have finished searching for objects, call the
+.B When you have finished searching for objects, call the
.B confdb_object_iter_destroy
library call to free up memory associated with the search context.
.BR
.BR
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_object_parent_get.3 b/man/confdb_object_parent_get.3
index ce48e71a..f626248a 100644
--- a/man/confdb_object_parent_get.3
+++ b/man/confdb_object_parent_get.3
@@ -1,72 +1,72 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_OBJECT_PARENT_GET 3 2008-04-17 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
confdb_parent_get \- Configuration Database Object Parent
.SH SYNOPSIS
.B #include <corosync/confdb.h>
.sp
.BI "confdb_error_t confdb_object_parent_get(confdb_handle_t " handle ", unsigned int " object_handle ", unsigned int " *parent_object_handle ");"
.SH DESCRIPTION
The
.B confdb_object_parent_get
returns the parent object handle of already known object.
-.B object_handle
+.B object_handle
is the handle of an existing object
.B parent_object_handle
returns the handle of its parent.
.SH RETURN VALUE
This call returns the CONFDB_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR confdb_overview (8),
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/confdb_overview.8 b/man/confdb_overview.8
index 61041428..b787e06f 100644
--- a/man/confdb_overview.8
+++ b/man/confdb_overview.8
@@ -1,77 +1,77 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CONFDB_OVERVIEW 8 2006-03-06 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
The CONFDB library is delivered with the corosync project. This library is used
to examine manipulate the configuration database used by corosync.
.PP
The library provides a mechanism to:
.PP
* Create new objects
.PP
* Create new key/value pairs within those objects
.PP
* Remove existing keys
.PP
* Remove an existing object and all it sub-objects and keys
.PP
* Read keys and values
.PP
* Iterate keys within an object
.PP
* Iterate subobjects within a parent object
.PP
* Find a named object
.PP
.SH BUGS
This software is not yet production, so there may still be some bugs.
.SH "SEE ALSO"
.BR confdb_initialize (3),
.BR confdb_finalize (3),
.BR confdb_fd_get (3),
.BR confdb_dispatch (3),
.BR confdb_object_create (3),
.BR confdb_object_destroy (3),
.BR confdb_object_parent_get (3),
-.BR confdb_key_create (3),
-.BR confdb_key_delete (3),
+.BR confdb_key_create (3),
+.BR confdb_key_delete (3),
.BR confdb_key_get (3),
.BR confdb_key_replace (3),
.BR confdb_object_find_start (3),
.BR confdb_object_find (3),
-.BR confdb_object_iter_start (3),
-.BR confdb_object_iter (3),
-.BR confdb_key_iter_start (3),
-.BR confdb_key_iter (3),
+.BR confdb_object_iter_start (3),
+.BR confdb_object_iter (3),
+.BR confdb_key_iter_start (3),
+.BR confdb_key_iter (3),
.PP
diff --git a/man/coroipc_overview.8 b/man/coroipc_overview.8
index 3d751a65..bd47bba9 100644
--- a/man/coroipc_overview.8
+++ b/man/coroipc_overview.8
@@ -1,176 +1,176 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Steven Dake (sdake@redhat.com)
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH COROIPC_OVERVIEW 8 2009-03-21 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
The coroipcs and coroipcc libraries provide a generically reusable very high
performance shared memory IPC sytem for client and service applications.
It supports many features including:
.PP
65536 user services and 65536 command ids per service.
.PP
Shared memory implementation for very high performance.
.PP
A synchronous request/response channel and asynchronous response channel
per ipc connection.
.PP
User defined private data per IPC connection.
.PP
Ability to call a function per service on ipc connection and disconnection.
.PP
Authenticated IPC connection with ability for developer to define which
UIDs and GIDs are valid at connection time.
.PP
Fully abstracted poll system so that any poll library may be used.
.PP
User defined selector for determining the proper function to call per
service and id.
.SH Description of the libraries
There are two shared libraries available for developing IPC client applications.
The first library is coroipcs.so which is responsible for the server
implementation. This library should be linked with the server and then
initialized with coroipcs_init(3).
Once the library is initialized, it will provide service to coroipcc.so library
users.
The second library is coroipcc.so which is responsible for the client
implementation. This library should be linked with the client and requires
no initialization. This library provides communication functions for sending
and receiving synchronous requests, and also reading asynchronous message
requests from the server.
.SH Initializing the coroipcs library
To use the coroipcs library, the developer creates a coroipcs_init_state
structure and populates it with function names. The functions do various
operations described in coroipcs_init(3) man page. Not all operations must
be specified. If some are missing, the corosync ipcs library will
automatically populate the structure with internal versions which provide
basic functionality.
.SH Communicating with the coroipcc clients
Every ipc connection is represented by a void * pointer which uniquely
identifies the data set for the IPC connection. Each IPC connection also
contains user defined private data. To obtain this private data pointer, the
function coroipcs_private_data_get(3) function can be called.
There are two channels for communication. The primary channel is the
synchronous request/response channel. Another channel is available for out of
band asynchronous responses from the server.
To send a response on the syncronous channel, coroipcs_response_send(3) or
coroipcs_response_iov_send(3) should be used. To send a message on the
asynchronous channel, coroipcs_dispatch_send(3) or coroipc_dispatch_iov_send(3)
should be used.
.SH The abstracted poll system
There are many different poll systems in use in applications. They are usually
intricately tied up in the implementation of the application and each provide
different APIs and functionality. To manage this, the coroipcs library
provides callbacks in coroipcs_init(3) which should be called when a new
connection should be added for accept system calls or to dispatch messages.
These callbacks add the relevant fd to the application's poll system. When the
application poll system triggers the callback registered by the user defined
poll adding functions, they then call either coroipc_handler_accept(3) or
coroipc_handler_dispatch(3).
.SH Initializing the coroipcc library
No initialization is required in the coroipcc library.
.SH Lifecycle of an IPC connection.
An IPC connection is made to the server with coroipcc_service_connect(3). This
function connects to the server and requests channels be created for
communication. To disconnect, the client either exits or executes the
function coroipcc_service_disconnect(3).
.SH Synchronous communication
-There are two functions for sending a request and receiving a response. The
+There are two functions for sending a request and receiving a response. The
first function coroipcc_msg_send_reply_receive(3) sends an iovector request
-and receives a response. This function copies the response into the response
+and receives a response. This function copies the response into the response
buffer. the second function coroipcc_msg_end_reply_receive_in_buf(3) does not
copy the response buffer and allows for zero-copy reading of the response
when the lifetime of the response buffer is known.
.SH Asynchronous communication
The coroipcc_dispatch_recv(3) function receives an out-of-band asyncronous
message. Unlike the synchronous communication channel, the asynchronous
messages are queued and can provide very high out-of-band performance.
To determine when to call coroipcc_dispatch_recv(3) the corosync_fd_get(3) call
is used to obtain a file descriptor used in the poll(2) or select(2) system
calls.
Finally the current dispatch flow control state can be obtained with
coroipcc_flow_control_get(3).
.SH Performance
The ipc system is tuned for very high performance while also being comletely
abstracted from the underlying poll mechanism and any internalisms required
by the server. The ipc system achieves such high performance by using shared
memory as oppossed to slower techniques such as UNIX_PF sockets.
We intend to do further development to allow syncronous requests to return
messages in an asyncronous way to avoid blocking involved in the syncronous
request/response model used today for higher throughput in some use cases.
.SH Security
The ipc system uses default operating system security mechanics to ensure
ipc connections are validated. A callback used with coroipcs_init(3) is called
for every new ipc connection with the parameters of UID and GID. The callback
then determines if the UID and GID are authenticated for communication. More
about this topic can be viewed in the coroipcs_init(3) man page.
.SH "SEE ALSO"
.BR coroipcs_ipc_init (3),
.BR coroipcs_ipc_exit (3),
.BR coroipcs_private_data_get (3),
.BR coroipcs_respone_send (3),
.BR coroipcs_response_iov_send (3),
.BR coroipcs_dispatch_send (3),
.BR coroipcs_dispatch_iov_send (3),
.BR coroipcs_refcount_inc (3),
.BR coroipcs_refcount_dec (3),
.BR coroipcs_handler_accept (3),
.BR coroipcs_handler_dispatch (3),
.BR cooripcc_service_connect (3),
.BR coroipcc_service_disconnect (3),
.BR coroipcc_msg_send_reply_receive (3),
.BR coroipcc_msg_send_reply_receive_in_buf (3),
.BR coroipcc_dispatch_recv (3),
.BR coroipcc_fd_get(3),
.BR coroipcc_dispatch_flow_control_get (3)
diff --git a/man/corosync-objctl.8 b/man/corosync-objctl.8
index 250a99c5..b83e172f 100644
--- a/man/corosync-objctl.8
+++ b/man/corosync-objctl.8
@@ -1,117 +1,117 @@
.\"/*
.\" * Copyright (c) 2008 Allied Telesis Labs NZ.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Angus Salkeld (angus.salkeld@alliedtelesis.co.nz)
.\" *
.\" * 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.
.\" */
.TH COROSYNC-OBJCTL 8 2008-07-29
.SH NAME
corosync-objctl \- Configure objects in the Object Database
.SH SYNOPSIS
.B "corosync-objctl [\-c|\-w|\-d|\-a|\-t\-h] <OBJECT-SPEC>..."
.SH DESCRIPTION
.B corosync-objctl
is used to configure objects within the object database at runtime.
.SH OBJECT-SPEC
.TP
There are two types of entities
.B Objects
and
.B Key=Value pairs
.TP
.B Objects
Objects are container like entities that can hold other entities.
They are specified as "objectA"."objectB".
An example is logging.logger.
.TP
.B Key=Value pairs
These are the entities that actually hold values (read database "fields").
They are specified as object.key=value or just object.key if you are reading.
.SH OPTIONS
.TP
.B -c
Create a new object.
.TP
.B -d
Delete an existing object.
.TP
.B -w
Use this option when you want to write a new value to a key.
.TP
.B -a
Display all values currently available.
.TP
.B -t
Track changes to an object and it's children. As changes are made to the object
they are printed out. this is kind of like a "tail -f" for the object database.
.TP
.B -h
Print basic usage.
.SH EXAMPLES
.TP
Print the objOne object (shouldn't exist yet).
$ corosync-objctl objOne
.TP
Create the objOne object.
$ corosync-objctl -c objOne
.TP
Print the objOne object (empty).
$ corosync-objctl objOne
.br
objOne
.TP
Write two new keys to the objOne object.
$ corosync-objctl -w objOne.max=3000 objOne.min=100
.TP
Print the objOne object (with the two new keys).
$ corosync-objctl objOne
.br
objOne.min=100
.br
objOne.max=3000
.TP
Delete the objOne.min key
$ corosync-objctl -d objOne.min=100
.TP
Prove that is gone.
$ corosync-objctl objOne
.br
objOne.max=3000
.TP
Delete the whole objOne object.
$ corosync-objctl -d objOne
.TP
Prove that is gone.
$ corosync-objctl objOne
.SH SEE ALSO
.BR confdb_initialize (3),
.SH AUTHOR
Angus Salkeld
.PP
diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
index 770fe9a3..1e44007d 100644
--- a/man/corosync.conf.5
+++ b/man/corosync.conf.5
@@ -1,544 +1,544 @@
.\"/*
.\" * Copyright (c) 2005 MontaVista Software, Inc.
.\" * Copyright (c) 2006 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.
.\" */
.TH COROSYNC_CONF 5 2006-03-28 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
corosync.conf - corosync executive configuration file
.SH SYNOPSIS
/etc/corosync.conf
.SH DESCRIPTION
The corosync.conf instructs the corosync executive about various parameters
needed to control the corosync executive. The configuration file consists of
bracketed top level directives. The possible directive choices are
.IR "totem { } , logging { }.
These directives are described below.
.TP
totem { }
This top level directive contains configuration options for the totem protocol.
.TP
logging { }
This top level directive contains configuration options for logging.
.TP
event { }
This top level directive contains configuration options for the event service.
.TP
aisexec { }
This top level directive contains configuration options for user privilegies.
.PP
.PP
-Within the
+Within the
.B totem
directive, an interface directive is required. There is also one configuration
option which is required:
.PP
.PP
-Within the
+Within the
.B interface
sub-directive of totem there are four parameters which are required:
.TP
ringnumber
This specifies the ring number for the interface. When using the redundant
ring protocol, each interface should specify separate ring numbers to uniquely
identify to the membership protocol which interface to use for which redundant
ring.
.TP
bindnetaddr
This specifies the address which the corosync executive should bind.
This address should always end in zero. If the totem traffic should
be routed over 192.168.5.92, set bindnetaddr to 192.168.5.0.
This may also be an IPV6 address, in which case IPV6 networking will be used.
In this case, the full address must be specified and there is no automatic
selection of the network interface within a specific subnet as with IPv4.
If IPv6 networking is used, the nodeid field must be specified.
.TP
mcastaddr
This is the multicast address used by corosync executive. The default
should work for most networks, but the network administrator should be queried
about a multicast address to use. Avoid 224.x.x.x because this is a "config"
multicast address.
This may also be an IPV6 multicast address, in which case IPV6 networking
will be used. If IPv6 networking is used, the nodeid field must be specified.
.TP
mcastport
This specifies the UDP port number. It is possible to use the same multicast
address on a network with the corosync services configured for different
UDP ports.
.PP
.PP
-Within the
-.B totem
+Within the
+.B totem
directive, there are seven configuration options of which one is required,
five are optional, and one is required when IPV6 is configured in the interface
subdirective. The required directive controls the version of the totem
configuration. The optional option unless using IPV6 directive controls
identification of the processor. The optional options control secrecy and
authentication, the redundant ring mode of operation, maximum network MTU,
and number of sending threads, and the nodeid field.
.TP
version
This specifies the version of the configuration file. Currently the only
valid version for this directive is 2.
.PP
.PP
.TP
nodeid
This configuration option is optional when using IPv4 and required when using
IPv6. This is a 32 bit value specifying the node identifier delivered to the
cluster membership service. If this is not specified with IPv4, the node id
will be determined from the 32 bit IP address the system to which the system
is bound with ring identifier of 0. The node identifier value of zero is
reserved and should not be used.
.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
sober128 encryption algorithm to protect data from eavesdropping.
Enabling this option adds a 36 byte header to every message sent by totem which
reduces total throughput. Encryption and authentication consume 75% of CPU
cycles in aisexec as measured with gprof when enabled.
For 100mbit networks with 1500 MTU frame transmissions:
A throughput of 9mb/sec is possible with 100% cpu utilization when this
option is enabled on 3ghz cpus.
A throughput of 10mb/sec is possible wth 20% cpu utilization when this
optin is disabled on 3ghz cpus.
For gig-e networks with large frame transmissions:
A throughput of 20mb/sec is possible when this option is enabled on
3ghz cpus.
A throughput of 60mb/sec is possible when this option is disabled on
3ghz cpus.
The default is on.
.TP
rrp_mode
This specifies the mode of redundant ring, which may be none, active, or
passive. Active replication offers slightly lower latency from transmit
to delivery in faulty network environments but with less performance.
Passive replication may nearly double the speed of the totem protocol
if the protocol doesn't become cpu bound. The final option is none, in
which case only one network interface will be used to operate the totem
protocol.
If only one interface directive is specified, none is automatically chosen.
If multiple interface directives are specified, only active or passive may
be chosen.
.TP
netmtu
This specifies the network maximum transmit unit. To set this value beyond
1500, the regular frame MTU, requires ethernet devices that support large, or
also called jumbo, frames. If any device in the network doesn't support large
frames, the protocol will not operate properly. The hosts must also have their
mtu size set from 1500 to whatever frame size is specified here.
Please note while some NICs or switches claim large frame support, they support
9000 MTU as the maximum frame size including the IP header. Setting the netmtu
and host MTUs to 9000 will cause totem to use the full 9000 bytes of the frame.
Then Linux will add a 18 byte header moving the full frame size to 9018. As a
-result some hardware will not operate properly with this size of data. A netmtu
+result some hardware will not operate properly with this size of data. A netmtu
of 8982 seems to work for the few large frame devices that have been tested.
Some manufacturers claim large frame support when in fact they support frame
sizes of 4500 bytes.
Increasing the MTU from 1500 to 8982 doubles throughput performance from 30MB/sec
-to 60MB/sec as measured with evsbench with 175000 byte messages with the secauth
+to 60MB/sec as measured with evsbench with 175000 byte messages with the secauth
directive set to off.
When sending multicast traffic, if the network frequently reconfigures, chances are
that some device in the network doesn't support large frames.
Choose hardware carefully if intending to use large frame support.
The default is 1500.
.TP
threads
This directive controls how many threads are used to encrypt and send multicast
messages. If secauth is off, the protocol will never use threaded sending.
If secauth is on, this directive allows systems to be configured to use
multiple threads to encrypt and send multicast messages.
A thread directive of 0 indicates that no threaded send should be used. This
-mode offers best performance for non-SMP systems.
+mode offers best performance for non-SMP systems.
The default is 0.
.TP
vsftype
This directive controls the virtual synchrony filter type used to identify
a primary component. The preferred choice is YKD dynamic linear voting,
however, for clusters larger then 32 nodes YKD consumes alot of memory. For
-large scale clusters that are created by changing the MAX_PROCESSORS_COUNT
+large scale clusters that are created by changing the MAX_PROCESSORS_COUNT
#define in the C code totem.h file, the virtual synchrony filter "none" is
recommended but then AMF and DLCK services (which are currently experimental)
are not safe for use.
The default is ykd. The vsftype can also be set to none.
-Within the
-.B totem
+Within the
+.B totem
directive, there are several configuration options which are used to control
the operation of the protocol. It is generally not recommended to change any
of these values without proper guidance and sufficient testing. Some networks
may require larger values if suffering from frequent reconfigurations. Some
applications may require faster failure detection times which can be achieved
by reducing the token timeout.
.TP
token
This timeout specifies in milliseconds until a token loss is declared after not
receiving a token. This is the time spent detecting a failure of a processor
in the current configuration. Reforming a new configuration takes about 50
milliseconds in addition to this timeout.
The default is 1000 milliseconds.
.TP
token_retransmit
This timeout specifies in milliseconds after how long before receiving a token
the token is retransmitted. This will be automatically calculated if token
is modified. It is not recommended to alter this value without guidance from
the corosync community.
The default is 238 milliseconds.
.TP
hold
This timeout specifies in milliseconds how long the token should be held by
the representative when the protocol is under low utilization. It is not
recommended to alter this value without guidance from the corosync community.
The default is 180 milliseconds.
.TP
retransmits_before_loss
This value identifies how many token retransmits should be attempted before
forming a new configuration. If this value is set, retransmit and hold will
be automatically calculated from retransmits_before_loss and token.
The default is 4 retransmissions.
.TP
join
-This timeout specifies in milliseconds how long to wait for join messages in
+This timeout specifies in milliseconds how long to wait for join messages in
the membership protocol.
The default is 100 milliseconds.
.TP
send_join
This timeout specifies in milliseconds an upper range between 0 and send_join
to wait before sending a join message. For configurations with less then
32 nodes, this parameter is not necessary. For larger rings, this parameter
is necessary to ensure the NIC is not overflowed with join messages on
formation of a new ring. A reasonable value for large rings (128 nodes) would
be 80msec. Other timer values must also change if this value is changed. Seek
advice from the corosync mailing list if trying to run larger configurations.
The default is 0 milliseconds.
.TP
consensus
This timeout specifies in milliseconds how long to wait for consensus to be
achieved before starting a new round of membership configuration.
The default is 200 milliseconds.
.TP
merge
This timeout specifies in milliseconds how long to wait before checking for
a partition when no multicast traffic is being sent. If multicast traffic
is being sent, the merge detection happens automatically as a function of
the protocol.
The default is 200 milliseconds.
.TP
downcheck
This timeout specifies in milliseconds how long to wait before checking
that a network interface is back up after it has been downed.
The default is 1000 millseconds.
.TP
fail_to_recv_const
This constant specifies how many rotations of the token without receiving any
of the messages when messages should be received may occur before a new
configuration is formed.
The default is 50 failures to receive a message.
.TP
seqno_unchanged_const
This constant specifies how many rotations of the token without any multicast
traffic should occur before the merge detection timeout is started.
The default is 30 rotations.
.TP
heartbeat_failures_allowed
[HeartBeating mechanism]
Configures the optional HeartBeating mechanism for faster failure detection. Keep in
-mind that engaging this mechanism in lossy networks could cause faulty loss declaration
-as the mechanism relies on the network for heartbeating.
+mind that engaging this mechanism in lossy networks could cause faulty loss declaration
+as the mechanism relies on the network for heartbeating.
-So as a rule of thumb use this mechanism if you require improved failure in low to
+So as a rule of thumb use this mechanism if you require improved failure in low to
medium utilized networks.
This constant specifies the number of heartbeat failures the system should tolerate
before declaring heartbeat failure e.g 3. Also if this value is not set or is 0 then the
heartbeat mechanism is not engaged in the system and token rotation is the method
of failure detection
The default is 0 (disabled).
.TP
max_network_delay
[HeartBeating mechanism]
This constant specifies in milliseconds the approximate delay that your network takes
to transport one packet from one machine to another. This value is to be set by system
engineers and please dont change if not sure as this effects the failure detection
mechanism using heartbeat.
The default is 50 milliseconds.
.TP
window_size
This constant specifies the maximum number of messages that may be sent on one
token rotation. If all processors perform equally well, this value could be
large (300), which would introduce higher latency from origination to delivery
for very large rings. To reduce latency in large rings(16+), the defaults are
a safe compromise. If 1 or more slow processor(s) are present among fast
processors, window_size should be no larger then 256000 / netmtu to avoid
overflow of the kernel receive buffers. The user is notified of this by
the display of a retransmit list in the notification logs. There is no loss
of data, but performance is reduced when these errors occur.
The default is 50 messages.
.TP
max_messages
This constant specifies the maximum number of messages that may be sent by one
processor on receipt of the token. The max_messages parameter is limited to
256000 / netmtu to prevent overflow of the kernel transmit buffers.
The default is 17 messages.
.TP
rrp_problem_count_timeout
This specifies the time in milliseconds to wait before decrementing the
problem count by 1 for a particular ring to ensure a link is not marked
faulty for transient network failures.
The default is 1000 milliseconds.
.TP
rrp_problem_count_threshold
This specifies the number of times a problem is detected with a link before
setting the link faulty. Once a link is set faulty, no more data is
transmitted upon it. Also, the problem counter is no longer decremented when
the problem count timeout expires.
A problem is detected whenever all tokens from the proceeding processor have
not been received within the rrp_token_expired_timeout. The
rrp_problem_count_threshold * rrp_token_expired_timeout should be atleast 50
milliseconds less then the token timeout, or a complete reconfiguration
may occur.
The default is 20 problem counts.
.TP
rrp_token_expired_timeout
This specifies the time in milliseconds to increment the problem counter for
the redundant ring protocol after not having received a token from all rings
for a particular processor.
This value will automatically be calculated from the token timeout and
problem_count_threshold but may be overridden. It is not recommended to
override this value without guidance from the corosync community.
The default is 47 milliseconds.
.PP
-Within the
+Within the
.B logging
directive, there are several configuration options which are all optional.
.PP
The following 3 options are valid only for the top level logging directive:
.TP
timestamp
This specifies that a timestamp is placed on all log messages.
The default is off.
.TP
fileline
This specifies that file and line should be printed.
The default is off.
.TP
function_name
This specifies that the code function name should be printed.
The default is off.
.PP
The following options are valid both for top level logging directive
and they can be overriden in logger_subsys entries.
.TP
to_stderr
.TP
to_logfile
.TP
to_syslog
These specify the destination of logging output. Any combination of
these options may be specified. Valid options are
.B yes
and
.B no.
The default is syslog and stderr.
.TP
logfile
-If the
+If the
.B to_logfile
directive is set to
.B yes
, this option specifies the pathname of the log file.
No default.
.TP
logfile_priority
This specifies the logfile priority for this particular subsystem. Ignored if debug is on.
Possible values are: alert, crit, debug (same as debug = on), emerg, err, info, notice, warning.
The default is: info.
-.TP
+.TP
syslog_facility
This specifies the syslog facility type that will be used for any messages
-sent to syslog. options are daemon, local0, local1, local2, local3, local4,
-local5, local6 & local7.
+sent to syslog. options are daemon, local0, local1, local2, local3, local4,
+local5, local6 & local7.
The default is daemon.
.TP
syslog_priority
This specifies the syslog level for this particular subsystem. Ignored if debug is on.
Possible values are: alert, crit, debug (same as debug = on), emerg, err, info, notice, warning.
The default is: info.
.TP
debug
This specifies whether debug output is logged for this particular logger.
The default is off.
.TP
tags
This specifies which tags should be traced for this particular logger.
Set debug directive to
.B on
in order to enable tracing using tags.
Values are specified using a vertical bar as a logical OR separator:
enter|leave|trace1|trace2|trace3|...
The default is none.
.PP
-Within the
+Within the
.B logging
directive, logger_subsys directives are optional.
.PP
-Within the
+Within the
.B logger_subsys
sub-directive, all of the above logging configuration options are valid and
can be used to override the default settings.
The subsys entry, described below, is mandatory to identify the subsystem.
.TP
subsys
This specifies the subsystem identity (name) for which logging is specified. This is the
name used by a service in the log_init () call. E.g. 'CKPT'. This directive is
required.
.PP
Within the
.B aisexec
directive, there are two configuration options which are all optional:
.TP
user
.TP
group
These specify the user and group, which is able to run and use corosync.
In any case, this is able to do root:root. But if you don't want run
corosync as root, you can use this directives.
The default is ais.
.SH "FILES"
.TP
/etc/corosync.conf
The corosync executive configuration file.
.SH "SEE ALSO"
.BR corosync_overview (8)
.PP
diff --git a/man/corosync_overview.8 b/man/corosync_overview.8
index 07a0ba1f..69c5bdc7 100644
--- a/man/corosync_overview.8
+++ b/man/corosync_overview.8
@@ -1,272 +1,272 @@
.\"/*
.\" * Copyright (c) 2005 MontaVista Software, Inc.
.\" * Copyright (c) 2006 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.
.\" */
.TH COROSYNC_OVERVIEW 8 2006-05-10 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
The corosync project is a project to implement a production quality "Revised BSD"
licensed implementation of the most recent SA Forum's Application Interface
Specification. The Application Interface Specification is a software API and
policies which are used to develop applications that maintain service during
faults. The API consists of Availability Management Framework (AMF) which
provides application failover, Cluster Membership (CLM), Checkpointing (CKPT),
Eventing (EVT), Messaging (MSG), and Distributed Locking (DLOCK).
Currently Messaging is unimplemented.
Faults occur for various reasons:
.PP
* Application Faults
.PP
* Middleware Faults
.PP
* Operating System Faults
.PP
* Hardware Faults
The major focus of high availability in the past has been to mask hardware
faults. Faults in other components of the system have gone unsolved until
AIS. AIS can mask many types of faults in applications, middleware,
operating systems, or even hardware by providing a simple framework
for allowing developers to create redundant applications. These redundant
applications can be distributed over multiple nodes such that if any one
node faults, another node can recover.
Application programmers develop applications to periodically record their
state using the checkpointing service. When an active application fails,
a standby application recovers the state of the application. This
technique, called stateful application failover, provides the fundamental
difference between corosync and other systems that have come before it.
With stateful application failover, the end-application user doesn't
have to reload the application or redial a telephone. The full state
is recorded, so the end-application user sees no interruption in service.
Because programmers can now distribute applications across multiple
processes or nodes, a mechanism must exist for them to communicate.
This mechanism is provided by two services. The event service provides
a publish/subscribe model for events. The messaging service provides
end to end messaging. Finally a mechanism to synchronize access is
-provided by the distributed lock service.
+provided by the distributed lock service.
The corosync project also provides a group messaging toolkit called EVS.
The EVS service implements a messaging model known as Extended Virtual
Synchrony. This model allows one sender to transmit to many receivers.
Certain guarantees are provided for message and membership delivery
which make virtual synchrony ideal for developing distributed applications.
.SH QUICKSTART
The corosync executive must be configured. In the directory conf in the
source distribution are several files that must be copied to the /etc/ais
directory. If corosync is packaged by a distro, this may be complete.
The directory contains the file corosync.conf. Please read the corosync.conf(5)
man page for details on the configuration options. The corosync project will
work out of the box with the default configuration options, although the
administrator may desire different options.
An user and group of the name "ais" must be added to the system. If corosync
is packaged from a distro, this step should already be completed.
This can be achieved by executing:
[root@slickdeal root]# adduser ais -g ais
The corosync executive uses cryptographic techniques to ensure authenticity
and privacy of the messages. In order for corosync to be secure and operate,
a private key must be generated and shared to all processors.
First generate the key on one of the nodes:
unix# ais-keygen
corosync authentication key generator.
.PP
Gathering 1024 bits for key from /dev/random.
.PP
Writing corosync key to /etc/ais/authkey.
.PP
After this operation, a private key will be in the file /etc/ais/authkey.
This private key must be copied to every processor in the cluster. If the
private key isn't the same for every node, those nodes with nonmatching private
keys will not be able to join the same configuration.
Copy the key to some security transportable storage or use ssh to transmit the
key from node to node. Then install the key with the command:
unix#: install -D --group=0 --owner=0 --mode=0400 /path_to_authkey/authkey /etc/ais/authkey
If a message "Invalid digest" appears from the corosync executive, the keys
are not consistent between processors.
Finally run the corosync executive. If corosync is packaged from a distro, it
may be set to start on system start. It may also be turned off by default in
which case the init script for corosync must be enabled.
After running aisexec, a list of all processors IP addresses running the ais
executive and configured on the same multicast address will appear. If they
don't appear, there may be a problem with multicast in the distro or hardware.
If this happens, participation in the corosync mailing list may help solve the
problem. The email address is corosync@lists.osdl.org.
.SH USING LIBRARIES
The corosync AIS libraries have header files which must be included in the
developer's application. Once the header file is included, the developer can
reference the AIS interfaces.
The corosync project recommends to distros to place include files in
/usr/include/corosync. The following include lines must be added to
-the application to use each of the following services:
+the application to use each of the following services:
#include <corosync/saClm.h> For the Cluster Membership B.01.01 service.
.PP
#include <corosync/saCkpt.h> For the Checkpointing B.01.01 service.
.PP
#include <corosync/saEvt.h> For the Eventing B.01.01 service.
.PP
#include <corosync/ais_amf.h> For the AMF A.01.01 service.
.PP
The corosync project recommends to distros to place library files in
/usr/lib. The following link lines must be added to the LDFLAGS section
of the makefile.
-lsaClm For the Cluster Membership B.01.01 service
.PP
-lsaCkpt For the Checkpointing B.01.01 service
.PP
-lsaEvt For the Eventing B.01.01 service
.PP
-lsaAmf For the AMF A.01.01 service
.PP
-lais Specify this to get access to all AIS libraries without specifying
each library individually.
.SH IPv6
The corosync project supports both IPv4 and IPv6 network addresses. The entire
cluster must use either IPv4 or IPv6 for the cluster communication mechanism.
In order to use IPv6, IPv6 addresses must be specified in the bindnetaddr and
mcastaddr fields in the configuration file. The nodeid field must also be
set.
An example of this is:
nodeid: 2
bindnetaddr: fec0::1:a800:4ff:fe00:20
mcastaddr: ff05::1
To configure a host for IPv6, use the ifconfig program to add interfaces:
box20: ifconfig eth0 add fec0::1:a800:4ff:fe00:20/64
box30: ifconfig eth0 add fec0::1:a800:4ff:fe00:30/64
If the /64 is not specified, a route for the IPv6 network will not be configured
which will cause significant problems. Make sure a route is available for
IPv6 traffic.
.SH ARCHITECTURE
The AIS libraries are a thin IPC interface to the corosync executive. The
corosync executive provides services for the SA Forum AIS libraries as well
as the EVS and CPG libraries.
The corosync executive uses the Totem extended virtual synchrony protocol. The
advantage to the end user is excellent performance characteristics and a proven
protocol with excellent reliability. This protocol connects the processors
in a configuration together so they may communicate.
.SH ENVIRONMENT VARIABLES
The corosync executive process uses four environment variables during startup.
If these environment variables are not set, defaults will be used.
.TP
COROSYNC_MAIN_CONFIG_FILE
This specifies the fully qualified path to the corosync configuration file.
The default is /etc/ais/corosync.conf.
.TP
COROSYNC_AMF_CONFIG_FILE
This specifies the fully qualified path to the corosync Availability Management
Framework configuration file.
The default is /etc/ais/amf.conf.
.TP
COROSYNC_DEFAULT_CONFIG_IFACE
This specifies the LCRSO that is used to parse the configuration file. This
allows other configuration file parsers to be implemented within the system.
The default is to use the default corosync configuration file parser which
parses the format specified in corosync.conf (5).
.TP
COROSYNC_TOTEM_AUTHKEY_FILE
This specifies the fully qualified path to the shared key used to
authenticate and encrypt data used within the Totem protocol.
The default is /etc/ais/authkey.
.SH SECURITY
The corosync executive optionally encrypts all messages sent over the network
using the SOBER-128 stream cipher. The corosync executive uses HMAC and SHA1 to
authenticate all messages. The corosync executive library uses SOBER-128
as a pseudo random number generator. The EVS library feeds the PRNG using
the /dev/random Linux device.
If membership messages can be captured by intruders, it is possible to execute
a denial of service attack on the cluster. In this scenario, the cluster is
likely already compromised and a DOS attack is the least of the administration's
worries.
The security in corosync does not offer perfect forward secrecy because the keys
are reused. It may be possible for an intruder by capturing packets in an
automated fashion to determine the shared key. No such automated attack has
been published as of yet. In this scenario, the cluster is likely already
compromised to allow the long-term capture of transmitted data.
For security reasons, the corosync executive binary aisexec should NEVER
be setuid or setgid in the filesystem.
.PP
.SH SAFTEST COMPLIANCE
The corosync libraries are now nearly compliant with every aspect of the SA
Forum's AIS specification. The AMF service, however, is not compliant with the
-B.01.01 specification. The remaining services pass most of the tests of the
+B.01.01 specification. The remaining services pass most of the tests of the
saftest suite against the B.01.01 specification.
.SH BUGS
The messaging service is partially implemented and not suitable for deployment.
The distributed locking service is buggy and not suitable for deployment.
The Availability Management Framework is under development and not suitable for
deployment..
.SH "SEE ALSO"
.BR corosync.conf (5),
.BR evs_overview (8)
.PP
diff --git a/man/cpg_context_get.3 b/man/cpg_context_get.3
index a843a925..d60617a0 100644
--- a/man/cpg_context_get.3
+++ b/man/cpg_context_get.3
@@ -1,64 +1,64 @@
.\"/*
.\" * Copyright (c) 2007 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_CONTEXT_GET 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_context_get \- Gets the context variable for a CPG instance
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_context_get(cpg_handle_t " handle ", void **" context ");
.SH DESCRIPTION
The
.B cpg_context_get
function is used to retrieve the context variable previously stored using
.B cpg_context_set(3)
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_context_set (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_context_set.3 b/man/cpg_context_set.3
index e8752bd0..9cf2f8d4 100644
--- a/man/cpg_context_set.3
+++ b/man/cpg_context_set.3
@@ -1,66 +1,66 @@
.\"/*
.\" * Copyright (c) 2007 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_CONTEXT_SET 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_context_set \- Sets the context variable for a CPG instance
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_context_set(cpg_handle_t " handle ", void *" context ");
.SH DESCRIPTION
The
.B cpg_context_set
function is used to set the context variable for a cpg instance. It has no
meaning insire libcpg itself and will not be touched by the library. It can
be retrieved using
.B cpg_context_get(3)
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3)
.BR cpg_context_get (3)
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_dispatch.3 b/man/cpg_dispatch.3
index 306e9363..439ecc58 100644
--- a/man/cpg_dispatch.3
+++ b/man/cpg_dispatch.3
@@ -1,100 +1,100 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_DISPATCH 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_dispatch \- Dispatches callbacks from the CPG service
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_dispatch(cpg_handle_t " handle ", cpg_dispatch_t *" dispatch_types ");
.SH DESCRIPTION
The
.B cpg_dispatch
function is used to dispatch configuration changes or messages from the
closed process groups API.
.PP
Each application may have several connections to the CPG API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection.
.PP
The
.I dispatch_types
argument is used to identify the type of dispatch to execute. The possible types are
defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
CPG_DISPATCH_ONE,
CPG_DISPATCH_ALL,
CPG_DISPATCH_BLOCKING
} cpg_dispatch_t;
.ta
.fi
.RE
.IP
.PP
.PP
The dispatch values have the following meanings:
.TP
.B CPG_DISPATCH_ONE
Dispatch atleast one callback, blocking until the callback is dispatched.
.TP
.B CPG_DISPATCH_ALL
Dispatch all waiting callbacks without blocking to wait for any callbacks.
.TP
.B CPG_DISPATCH_BLOCKING
Dispatch all callbacks blocking indefinately. This is used in a threaded
program where a thread is created, and then cpg_dispatch() is called immediately
from the created thread to execute callbacks.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3)
.PP
diff --git a/man/cpg_fd_get.3 b/man/cpg_fd_get.3
index a5940173..365d611e 100644
--- a/man/cpg_fd_get.3
+++ b/man/cpg_fd_get.3
@@ -1,70 +1,70 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_FD_GET 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_fd_get \- Dispatches callbacks from the CPG service
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_fd_get(cpg_handle_t " handle ", int *" fd ");
.SH DESCRIPTION
The
.B cpg_fd_get
function is used to retrieve the file descriptor that may be used with the poll
system call to determine when
.B cpg_dispatch(3)
won't block. The
.I handle
argument may not be used directly with
.B poll
because it is not the file descriptor, but instead an internal identifier used
by the CPG library.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3)
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_finalize.3 b/man/cpg_finalize.3
index 39391b64..4b7ca9c9 100644
--- a/man/cpg_finalize.3
+++ b/man/cpg_finalize.3
@@ -1,67 +1,67 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_FINALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_finalize \- Terminate a connection to the CPG service
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_finalize(cpg_handle_t " handle ");
.SH DESCRIPTION
The
.B cpg_finalize
function is used to close a connection to the closed process group API.
Once the connection is finalized, the handle may not be used again by applications.
No more callbacks will be dispatched from the
.B cpg_dispatch function.
.PP
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_initialize.3 b/man/cpg_initialize.3
index 3d764c02..91355e79 100644
--- a/man/cpg_initialize.3
+++ b/man/cpg_initialize.3
@@ -1,175 +1,175 @@
.\"/*
.\" * Copyright (c) 2006-2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CPG_INITIALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_initialize \- Create a new connection to the CPG service
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_initialize(cpg_handle_t *" handle ", cpg_callbacks_t *" callbacks ");
.SH DESCRIPTION
The
.B cpg_initialize
function is used to initialize a connection to the closed process groups API.
.PP
Each application may have several connections to the CPG API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection. The
.I handle
argument is then used in other function calls to identify the connection to be used
for communication with the CPG service.
.PP
Every time an CPG event occurs within the joined group, one of the callbacks specified by the argument
.I callbacks
is called. The callback functions are described by the following type definitions:
.PP
.PP
.IP
.RS
.ne 18
.nf
.ta 4n 20n 32n
typedef void (*cpg_deliver_fn_t) (
cpg_handle_t handle,
const struct cpg_name *group_name,
uint32_t nodeid,
uint32_t pid,
const void *msg,
size_t msg_len);
typedef void (*cpg_confchg_fn_t) (
cpg_handle_t handle,
const struct cpg_name *group_name,
const struct cpg_address *member_list, size_t member_list_entries,
const struct cpg_address *left_list, size_t left_list_entries,
const struct cpg_address *joined_list, size_t joined_list_entries);
typedef void (*cpg_groups_get_fn_t) (
cpg_handle_t handle,
uint32_t group_num,
uint32_t group_total,
const struct cpg_name *group_name,
struct cpg_address *member_list, size_t member_list_entries);
.ta
.fi
.RE
.IP
.PP
.PP
The
.I callbacks
argument is of the type:
.IP
.RS
.ne 18
.nf
.PP
typedef struct {
cpg_deliver_fn_t cpg_deliver_fn;
cpg_confchg_fn_t cpg_confchg_fn;
cpg_groups_get_fn_t cpg_groups_get_fn;
} cpg_callbacks_t;
.ta
.fi
.RE
.IP
.PP
When a configuration change occurs or a message is to be delivered one of the callbacks
is called from the
.B cpg_dispatch()
function. If a configuration change occurs,
.I cpg_confchg_fn
is called. If a delivery of a message occurs,
.I cpg_deliver_fn
is called.
The
.I cpg_address
-structure is defined
+structure is defined
.IP
.RS
.ne 18
.nf
.PP
struct cpg_address {
unsigned int nodeid;
unsigned int pid;
unsigned int reason;
};
.ta
.fi
.RE
.IP
.PP
where nodeid is a 32 bit unique node identifier, pid is the process ID of the process that has joined/left the group
or sent the message, and reason is an integer code indicating why the node join/left the group.
.PP
.IP
.RS
.ne 18
.nf
.PP
CPG_REASON_JOIN - the process joined a group using cpg_join().
CPG_REASON_LEAVE - the process left a group using cpg_leave()
CPG_REASON_NODEDOWN - the process left a group because the node left the cluster.
CPG_REASON_NODEUP - the process joined a group because it was already a member of a group on a node that has just joined the cluster
CPG_REASON_PROCDOWN - the process left a group without calling cpg_leave()
.ta
.fi
.RE
.IP
.PP
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_join.3 b/man/cpg_join.3
index bfe67b7a..92187fc8 100644
--- a/man/cpg_join.3
+++ b/man/cpg_join.3
@@ -1,108 +1,108 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_JOIN 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_join \- Joins one or more groups in the CPG library
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_join(cpg_handle_t " handle ", struct cpg_name *" group ");
.SH DESCRIPTION
The
.B cpg_join
function is used to join one group. When a group is joined, using the
.B cpg_mcast_joined(3)
function will multicast to the groups joined in the argument
-.I handle.
+.I handle.
The process will also get notifications of other processes joining
and leaving the group.
Messages that are sent to any of the groups joined to the parameter
.I handle
will be delivered by
.B cpg_dispatch(3).
.PP
This function may be only be called once for each handle. When a group has been joined
the process will start to receive callbacks relating to messages send from members
of the group or notifications of process joining/leaving the group.
.PP
Note that more than one process can join a CPG group and each will receive its
-own copy of any messages sent using
+own copy of any messages sent using
.I cpg_mcast_joined()
and its own confchg callback.
.PP
The argument
.I group
-is used to specify the group to join.
+is used to specify the group to join.
The
.I groups
argument is of the type struct cpg_name which is defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
struct cpg_name {
int length;
char value[128];
};
.ta
.fi
.RE
.IP
.PP
.PP
.SH RETURN VALUE
This call returns the CPG_OK value if successful, CPG_ERR_INVALID_PARAM if the
handle is already joined to a group.
.PP
.SH ERRORS
Not all errors are documented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_leave.3 b/man/cpg_leave.3
index 47b0de26..8fbfc429 100644
--- a/man/cpg_leave.3
+++ b/man/cpg_leave.3
@@ -1,73 +1,73 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_LEAVE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_leave \- Leave a group in the CPG library
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_leave(cpg_handle_t " handle ", struct cpg_name *" group ");
.SH DESCRIPTION
The
.B cpg_leave
function is used to leave a group. Once a group has been left the process will
-no longer receive messages or notifications about events in that group. NOTE: that a group is
+no longer receive messages or notifications about events in that group. NOTE: that a group is
only deemed to have left the group once it has been notified (by its confchg callback)
that is has left. So expect to receive at least one confchg callback after calling
this function.
The argument
.I group
is used to specify the group to leave. It is currently ignored as only one group
can be joined per handle. It is included here for to allow for future development.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_local_get.3 b/man/cpg_local_get.3
index 4ec8ecdf..5152e9fb 100644
--- a/man/cpg_local_get.3
+++ b/man/cpg_local_get.3
@@ -1,68 +1,68 @@
.\"/*
.\" * Copyright (c) 2007 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.
.\" */
.TH CPG_LOCAL_GET 3 2007-06-12 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_local_get \- Returns the local processor id
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_local_get(cpg_handle_t " handle ", unsigned int *" local_nodeid ");
.SH DESCRIPTION
The
.B cpg_local_get
function is used to determine the local processor's identifier.
.BR
The argument
.I handle
is used to reference the cpg instantiation.
-The argument
+The argument
.I local_nodeid
will return the 32 bit node id.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_mcast_joined.3 b/man/cpg_mcast_joined.3
index 42e0c882..8fc3daf9 100644
--- a/man/cpg_mcast_joined.3
+++ b/man/cpg_mcast_joined.3
@@ -1,137 +1,137 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_MCAST_JOINED 3 3004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_mcast_joined \- Multicasts to all groups joined to a handle
.SH SYNOPSIS
.B #include <sys/uio.h>
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_mcast_joined(cpg_handle_t " handle ", cpg_gurantee_t " guarantee ", struct iovec *" iovec ", int " iov_len ");
.SH DESCRIPTION
The
.B cpg_mcast_joined
function will multicast a message to all the processes that have been joined with the
.B cpg_join(3)
funtion for the same group name.
Messages that are sent to any of the groups joined to the parameter
.I handle
will be delivered to all subscribed processes in the system.
.PP
The argument
.I guarantee
requests a delivery guarantee for the message to be sent. The cpg_guarantee_t type is
defined by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
CPG_TYPE_UNORDERED, /* not implemented */
CPG_TYPE_FIFO, /* same as agreed */
CPG_TYPE_AGREED, /* implemented */
CPG_TYPE_SAFE /* not implemented */
} cpg_guarantee_t;
.ta
.fi
.RE
.IP
.PP
.PP
The meanings of the cpg_guarantee_t typedef are:
.TP
.B CPG_TYPE_UNORDERED
-Messages are guaranteed to be delivered, but with no particular order. This
+Messages are guaranteed to be delivered, but with no particular order. This
mode is unimplemented in the CPG library.
.TP
.B CPG_TYPE_FIFO
Messages are guaranteed to be delivered in first sent first delivery order.
In fact, this guarantee is equivalent to the CPG_TYPE_AGREED guarantee.
.TP
.B CPG_TYPE_AGREED
All processors must agree on the order of delivery. If a message is sent
from two or more processors at about the same time, the delivery will occur
in the same order to all processors.
.TP
.B CPG_TYPE_SAFE
All processors must agree on the order of delivery. Further all processors
must have a copy of the message before any delivery takes place. This mode is
unimplemented in the CPG library.
.PP
The
.I iovec
argument describes the scatter/gather list which is used to transmit a message. This
is a standard socket structure described by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
struct iovec
{
void *iov_base; /* Pointer to data. */
unsigned int iov_len; /* Length of data. */
};
.ta
.fi
.RE
.IP
.PP
.PP
The
.I iov_len
argument describes the number of entires in the
.I iovec
-argument.
+argument.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_join (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_membership_get.3 b/man/cpg_membership_get.3
index d9aa782a..997f6698 100644
--- a/man/cpg_membership_get.3
+++ b/man/cpg_membership_get.3
@@ -1,77 +1,77 @@
.\"/*
.\" * Copyright (c) 2006 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_MEMBERSHIP_GET 3 2006-02-06 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_membership_get \- Returns a list of members of a CPG library group
.SH SYNOPSIS
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_membership_get(cpg_handle_t " handle ", struct cpg_name *" groupName ", struct cpg_address *" member_list ", int *" member_list_entries ");
.SH DESCRIPTION
The
.B cpg_membership_get
function is used to determine the current processes in the configuration. You probably will not
need to call this function much as one of the first confchg callbacks you will get will be from
the cpg_join() function containing your process.
.BR
The argument
.I handle
is used to reference the cpg instantiation.
-The argument
+The argument
.I groupName
will return the name of the group
The argument
.I member_list
will return the list of processors in the current membership.
The argument
.I member_list_entries
should be set with the size of member_list and will return the size of the
member_list after return from the function.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_overview.8 b/man/cpg_overview.8
index 354d8e88..9742752c 100644
--- a/man/cpg_overview.8
+++ b/man/cpg_overview.8
@@ -1,66 +1,66 @@
.\"/*
.\" * Copyright (c) 2006-2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Patrick Caulfield <pcaulfie@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.
.\" */
.TH CPG_OVERVIEW 8 2009-4-15 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
The CPG library is delivered with the corosync project. This library is used
to create distributed applications that operate properly during partitions, merges,
and faults.
.PP
The library provides a mechanism to:
* handle abstraction for multiple instances of an CPG library in one application
* join one or more groups
* leave one or more groups
* Deliver messages to members of that group
* Deliver configuration changes
.PP
.SH SECURITY
If encryption is enabled in corosync.conf, the CPG library will encrypt and
authenticate message contents. Applications must run as the ais user to be
validated by corosync on IPC connection, otherwise they will be unable to
access the corosync services.
.SH "SEE ALSO"
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_join (3),
.BR cpg_leave (3),
.BR cpg_mcast_joined (3),
.BR cpg_membership_get (3)
.BR cpg_zcb_alloc (3)
.BR cpg_zcb_free (3)
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_zcb_alloc.3 b/man/cpg_zcb_alloc.3
index 9e94768d..5ee0f8d9 100644
--- a/man/cpg_zcb_alloc.3
+++ b/man/cpg_zcb_alloc.3
@@ -1,80 +1,80 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Steven Dake <sdake@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CPG_ZCB_ALLOC 2009-04-15 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_zcb_alloc \- Allocates a zero copy buffer
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_zcb_alloc(cpg_handle_t " handle ", size_t " size ", void **" buffer ");
.SH DESCRIPTION
The
.B cpg_zcb_alloc
function will allocate a zero copy buffer for use with the
.B cpg_zcb_mcast_joined(3)
funtion. This buffer should not be used in another thread while a
cpg_zcb_mcast_joined operation is taking place on the buffer. The buffer is
allocated via operating system mechanisms to avoid copying in the IPC layer.
.PP
The argument
.I handle
describes the handle on which the buffer will be allocated.
.PP
The argument
.I size
requests a buffer of size be allocated.
.PP
The
.I buffer
argument is set to the buffer address that is allocated by this operatoin.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_join (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_zcb_free.3 b/man/cpg_zcb_free.3
index daae971e..48f99f25 100644
--- a/man/cpg_zcb_free.3
+++ b/man/cpg_zcb_free.3
@@ -1,72 +1,72 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Steven Dake <sdake@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CPG_ZCB_FREE 2009-04-15 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_zcb_free \- Frees a zero copy buffer
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_zcb_fre(cpg_handle_t " handle ", void *" buffer ");
.SH DESCRIPTION
The
.B cpg_zcb_free
function will free a zero copy buffer.
.PP
The argument
.I handle
describes the handle on which the buffer will be allocated.
.PP
The argument
.I buffer
is the zero copy buffer to free.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_join (3),
.BR cpg_membership_get (3),
.BR cpg_zcb_alloc (3),
.BR cpg_zcb_free (3),
.BR cpg_zcb_mcast_joined (3)
.PP
diff --git a/man/cpg_zcb_mcast_joined.3 b/man/cpg_zcb_mcast_joined.3
index ca553023..57c71b8e 100644
--- a/man/cpg_zcb_mcast_joined.3
+++ b/man/cpg_zcb_mcast_joined.3
@@ -1,121 +1,121 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Steven Dake <sdake@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH CPG_ZCB_MCAST_JOINED 3 3004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
cpg_mcast_joined \- Multicasts a zero copy buffer to all groups joined to a handle
.SH SYNOPSIS
.B #include <sys/uio.h>
.B #include <corosync/cpg.h>
.sp
.BI "int cpg_zcb_mcast_joined(cpg_handle_t " handle ", cpg_gurantee_t " guarantee ", const void *" buffer "", int " msg_len ");
.SH DESCRIPTION
The
.B cpg_zcb_mcast_joined
function will multicast a zero copy buffer message to all the processes that
have been joined with the
.B cpg_join(3)
funtion for the same group name.
Messages that are sent to any of the groups joined to the parameter
.I handle
will be delivered to all subscribed processes in the system.
.PP
The argument
.I guarantee
requests a delivery guarantee for the message to be sent. The cpg_guarantee_t type is
defined by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
CPG_TYPE_UNORDERED, /* not implemented */
CPG_TYPE_FIFO, /* same as agreed */
CPG_TYPE_AGREED, /* implemented */
CPG_TYPE_SAFE /* not implemented */
} cpg_guarantee_t;
.ta
.fi
.RE
.IP
.PP
.PP
The meanings of the cpg_guarantee_t typedef are:
.TP
.B CPG_TYPE_UNORDERED
-Messages are guaranteed to be delivered, but with no particular order. This
+Messages are guaranteed to be delivered, but with no particular order. This
mode is unimplemented in the CPG library.
.TP
.B CPG_TYPE_FIFO
Messages are guaranteed to be delivered in first sent first delivery order.
In fact, this guarantee is equivalent to the CPG_TYPE_AGREED guarantee.
.TP
.B CPG_TYPE_AGREED
All processors must agree on the order of delivery. If a message is sent
from two or more processors at about the same time, the delivery will occur
in the same order to all processors.
.TP
.B CPG_TYPE_SAFE
All processors must agree on the order of delivery. Further all processors
must have a copy of the message before any delivery takes place. This mode is
unimplemented in the CPG library.
.PP
The
.I msg
argument describes the zero copy buffer which is used to transmit a message.
-this buffer must be allocated by
+this buffer must be allocated by
.B cpg_zcb_alloc(3).
.PP
The
.I msg_len
argument describes the number of bytes to be transmitted in the zero copy buffer.
.SH RETURN VALUE
This call returns the CPG_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR cpg_overview (8),
.BR cpg_initialize (3),
.BR cpg_finalize (3),
.BR cpg_fd_get (3),
.BR cpg_dispatch (3),
.BR cpg_leave (3),
.BR cpg_join (3),
.BR cpg_membership_get (3)
.BR cpg_zcb_alloc (3)
.BR cpg_zcb_free (3)
.PP
diff --git a/man/evs_dispatch.3 b/man/evs_dispatch.3
index f36f55dd..4967725c 100644
--- a/man/evs_dispatch.3
+++ b/man/evs_dispatch.3
@@ -1,101 +1,101 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_DISPATCH 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_dispatch \- Dispatches callbacks from the EVS service
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_dispatch(evs_handle_t " handle ", evs_dispatch_t *" dispatch_types ");
.SH DESCRIPTION
The
.B evs_dispatch
function is used to dispatch configuration changes or messages from the
extended virtual synchrony API.
.PP
Each application may have several connections to the EVS API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection.
.PP
The
.I dispatch_types
argument is used to identify the type of dispatch to execute. The possible types are
defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
EVS_DISPATCH_ONE,
EVS_DISPATCH_ALL,
EVS_DISPATCH_BLOCKING
} evs_dispatch_t;
.ta
.fi
.RE
.IP
.PP
.PP
The dispatch values have the following meanings:
.TP
.B EVS_DISPATCH_ONE
Dispatch atleast one callback, blocking until the callback is dispatched.
.TP
.B EVS_DISPATCH_ALL
Dispatch all waiting callbacks without blocking to wait for any callbacks.
.TP
.B EVS_DISPATCH_BLOCKING
Dispatch all callbacks blocking indefinately. This is used in a threaded
program where a thread is created, and then evs_dispatch() is called immediately
from the created thread to execute callbacks.
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_join (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_fd_get.3 b/man/evs_fd_get.3
index b88450e2..5ed6f8a9 100644
--- a/man/evs_fd_get.3
+++ b/man/evs_fd_get.3
@@ -1,68 +1,68 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_FD_GET 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_fd_get \- Dispatches callbacks from the EVS service
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_fd_get(evs_handle_t " handle ", int *" fd ");
.SH DESCRIPTION
The
.B evs_fd_get
function is used to retrieve the file descriptor that may be used with the poll
system call to determine when
.B evs_dispatch(3)
won't block. The
.I handle
argument may not be used directly with
.B poll
because it is not the file descriptor, but instead an internal identifier used
by the EVS library.
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_dispatch (3),
.BR evs_join (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_finalize.3 b/man/evs_finalize.3
index 75cc34b4..57fe2d20 100644
--- a/man/evs_finalize.3
+++ b/man/evs_finalize.3
@@ -1,64 +1,64 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_FINALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_finalize \- Terminate a connection to the EVS service
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_finalize(evs_handle_t " handle ");
.SH DESCRIPTION
The
.B evs_finalize
function is used to close a connection to the extended virtual synchrony API.
Once the connection is finalized, the handle may not be used again by applications.
No more callbacks will be dispatched from the
.B evs_dispatch function.
.PP
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_join (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_initialize.3 b/man/evs_initialize.3
index ac75bb48..69a719d1 100644
--- a/man/evs_initialize.3
+++ b/man/evs_initialize.3
@@ -1,140 +1,140 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_INITIALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_initialize \- Create a new connection to the EVS service
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_initialize(evs_handle_t *" handle ", evs_callbacks_t *" callbacks ");
.SH DESCRIPTION
The
.B evs_initialize
function is used to initialize a connection to the extended virtual synchrony API.
.PP
Each application may have several connections to the EVS API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection. The
.I handle
argument is then used in other function calls to identify the connection to be used
for communication with the EVS service.
.PP
Every time an EVS event occurs, one of the callbacks specified by the argument
.I callbacks
is called. The callback functions are described by the following type definitions:
.PP
.IP
.RS
.ne 18
.nf
.ta 4n 20n 32n
typedef void (*evs_deliver_fn_t) (
struct evs_address source_addr,
const void *msg,
size_t msg_len);
typedef void (*evs_confchg_fn_t) (
const struct evs_address *member_list, size_t member_list_entries,
const struct evs_address *left_list, size_t left_list_entries,
const struct evs_address *joined_list, size_t joined_list_entries);
.ta
.fi
.RE
.IP
.PP
.PP
The
.I callbacks
argument is of the type:
.IP
.RS
.ne 18
.nf
.PP
typedef struct {
evs_deliver_fn_t evs_deliver_fn;
evs_confchg_fn_t evs_confchg_fn;
} evs_callbacks_t;
.ta
.fi
.RE
.IP
.PP
When a configuration change occurs or a message is to be delivered one of the callbacks
is called from the
.B evs_dispatch()
function. If a configuration change occurs,
.I evs_confchg_fn
is called. If a delivery of a message occurs,
.I evs_deliver_fn
is called.
The
.I evs_address
-structure is defined
+structure is defined
.IP
.RS
.ne 18
.nf
.PP
struct evs_address {
unsigned int nodeid;
unsigned short family;
unsigned char addr[TOTEMIP_ADDRLEN];
};
.ta
.fi
.RE
.IP
.PP
where nodeid is a 32 bit unique node identifier, family is of the value AF_INET for an IPV4 network, or AF_INET6 for an IPV6 network, and addr is a 32 bit address for an IPV4 network, or 128 bit address for an IPV6 network.
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_join (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_join.3 b/man/evs_join.3
index 9f5bed64..7a88a880 100644
--- a/man/evs_join.3
+++ b/man/evs_join.3
@@ -1,103 +1,103 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_JOIN 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_join \- Joins one or more groups in the EVS library
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_join(evs_handle_t " handle ", evs_group_t *" groups ", int " group_entries ");
.SH DESCRIPTION
The
.B evs_join
function is used to join one or more groups. When a group is joined, using the
.B evs_mcast_joined(3)
function will multicast to the groups joined in the argument
.I handle.
Messages that are sent to any of the groups joined to the parameter
.I handle
will be delivered by
.B evs_dispatch(3).
.PP
This call may be used more then once on a handle, in which case the joined groups will
be all of the groups passed to the
.B evs_join(3)
function during the lifecycle of the parameter
.I handle.
.PP
The argument
.I groups
is used to specify the groups to join. A group is a 32 byte key. The key is
not a string, hence, the entire key is used when joining the channel. For that reason
the entire group should be initialized.
.PP
The argument
.I group_entries
specifies how many entries are located in the groups argument.
The
.I groups
argument is of the type evs_group_t which is defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef struct {
char key[32];
} evs_groups_t;
.ta
.fi
.RE
.IP
.PP
.PP
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_leave.3 b/man/evs_leave.3
index 76df8dbc..750b6820 100644
--- a/man/evs_leave.3
+++ b/man/evs_leave.3
@@ -1,98 +1,98 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_LEAVE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_leave \- Leave one or more groups in the EVS library
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_leave(evs_handle_t " handle ", evs_group_t *" groups ", int group_entries);
.SH DESCRIPTION
The
.B evs_leave
-function is used to leave one or more groups. The joined groups are used with
+function is used to leave one or more groups. The joined groups are used with
.B evs_mcast_joined(3)
function to multicast to the groups joined in the argument
.I handle.
Messages that are sent to any of the joined groups to the parameter
.I handle
will be delivered by
.B evs_dispatch(3).
.PP
This call may be used more then once on a handle.
.PP
The argument
.I groups
is used to specify the groups to leave. A group is a 32 byte key. The key is
not a string, hence, the entire key is used when leaveing the channel. For that reason
the entire group should be initialized.
.PP
The argument
.I group_entries
specifies how many entries are located in the groups argument.
The
.I groups
argument is of the type evs_group_t which is defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef struct {
char key[32];
} evs_groups_t;
.ta
.fi
.RE
.IP
.PP
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_join (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_mcast_groups.3 b/man/evs_mcast_groups.3
index f3d28f9c..1e68f84b 100644
--- a/man/evs_mcast_groups.3
+++ b/man/evs_mcast_groups.3
@@ -1,162 +1,162 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_MCAST_GROUPS 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_join \- Multicast a message to selected groups
.SH SYNOPSIS
.B #include <sys/uio.h>
.B #include <corosync/evs.h>
.sp
.BI "int evs_mcast_groups(evs_handle_t " handle ", evs_guraantee_t " guarantee ", evs_group_t *" groups ", int group_entries, struct iovec *" iovec ", int " iov_len ");
.SH DESCRIPTION
The
.B evs_mcast_groups(3)
function multicasts a message to all the groups specified in the arguemnt
.I groups.
Messages are delivered to all processors in the system that are described by the current
configuration.
.PP
The argument
.I handle
describes a handle created with
.B evs_initialize(3).
.PP
The argument
.I guarantee
requests a delivery guarantee for the message to be sent. The evs_guarantee_t type is
defined by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
EVS_TYPE_UNORDERED, /* not implemented */
EVS_TYPE_FIFO, /* same as agreed */
EVS_TYPE_AGREED, /* implemented */
EVS_TYPE_SAFE /* not implemented */
} evs_guarantee_t;
.ta
.fi
.RE
.IP
.PP
.PP
The meanings of the evs_guarantee_t typedef are:
.TP
.B EVS_GUARANTEE_UNORDERED
-Messages are guaranteed to be delivered, but with no particular order. This
+Messages are guaranteed to be delivered, but with no particular order. This
mode is unimplemented in the EVS library.
.TP
.B EVS_GUARANTEE_FIFO
Messages are guaranteed to be delivered in first sent first delivery order
from one one. In fact, this guarantee is actually the AGREED guarantee.
.TP
.B EVS_GUARANTEE_AGREED
All processors must agree on the order of delivery. If a message is sent
from two or more processors at about the same time, the delivery will occur
in the same order to all processors.
.TP
.B EVS_GUARANTEE_SAFE
All processors must agree on the order of delivery. Further all processors
must have a copy of the message before any delivery takes place. This mode is
unimplemented in the EVS library.
.PP
The
.I groups
argument is of the type evs_group_t which is defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef struct {
char key[32];
} evs_groups_t;
.ta
.fi
.RE
.IP
.PP
.PP
The
.I group_entries
argument describes the number of entries in the
.I group
argument.
.PP
The
.I iovec
argument describes the scatter/gather list which is used to transmit a message. This
is a standard socket structure described by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
struct iovec
{
void *iov_base; /* Pointer to data. */
unsigned int iov_len; /* Length of data. */
};
.ta
.fi
.RE
.IP
.PP
.PP
The
.I iovlen
argument describes the number of entires in the
.I iovec
-argument.
+argument.
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_leave (3),
.BR evs_join (3),
.BR evs_mcast_joined (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_mcast_joined.3 b/man/evs_mcast_joined.3
index a685e8b1..d9ba7322 100644
--- a/man/evs_mcast_joined.3
+++ b/man/evs_mcast_joined.3
@@ -1,135 +1,135 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_MCAST_JOINED 3 3004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_join \- Multicasts to all groups joined to an handle
.SH SYNOPSIS
.B #include <sys/uio.h>
.B #include <corosync/evs.h>
.sp
.BI "int evs_mcast_joined(evs_handle_t " handle ", evs_guraantee_t " guarantee ", struct iovec *" iovec ", int " iov_len ");
.SH DESCRIPTION
The
.B evs_mcast_joined
function is multicast a message to all the groups that have been joined with the
.B evs_join(3)
function for the argument
.I handle.
Messages that are sent to any of the groups joined to the parameter
.I handle
will be delivered to all processors in the system.
.PP
The argument
.I guarantee
requests a delivery guarantee for the message to be sent. The evs_guarantee_t type is
defined by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
EVS_TYPE_UNORDERED, /* not implemented */
EVS_TYPE_FIFO, /* same as agreed */
EVS_TYPE_AGREED, /* implemented */
EVS_TYPE_SAFE /* not implemented */
} evs_guarantee_t;
.ta
.fi
.RE
.IP
.PP
.PP
The meanings of the evs_guarantee_t typedef are:
.TP
.B EVS_GUARANTEE_UNORDERED
-Messages are guaranteed to be delivered, but with no particular order. This
+Messages are guaranteed to be delivered, but with no particular order. This
mode is unimplemented in the EVS library.
.TP
.B EVS_GUARANTEE_FIFO
Messages are guaranteed to be delivered in first sent first delivery order
from one one. In fact, this guarantee is actually the AGREED guarantee.
.TP
.B EVS_GUARANTEE_AGREED
All processors must agree on the order of delivery. If a message is sent
from two or more processors at about the same time, the delivery will occur
in the same order to all processors.
.TP
.B EVS_GUARANTEE_SAFE
All processors must agree on the order of delivery. Further all processors
must have a copy of the message before any delivery takes place. This mode is
unimplemented in the EVS library.
.PP
The
.I iovec
argument describes the scatter/gather list which is used to transmit a message. This
is a standard socket structure described by:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
struct iovec
{
void *iov_base; /* Pointer to data. */
unsigned int iov_len; /* Length of data. */
};
.ta
.fi
.RE
.IP
.PP
.PP
The
.I iovlen
argument describes the number of entires in the
.I iovec
-argument.
+argument.
.SH RETURN VALUE
This call returns the EVS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_leave (3),
.BR evs_join (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_membership_get.3 b/man/evs_membership_get.3
index a15872c9..d7adf5cb 100644
--- a/man/evs_membership_get.3
+++ b/man/evs_membership_get.3
@@ -1,72 +1,72 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_JOIN 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
evs_join \- Joins one or more groups in the EVS library
.SH SYNOPSIS
.B #include <corosync/evs.h>
.sp
.BI "int evs_membership_get(evs_handle_t " handle ", struct evs_address *" local_addr ", struct evs_address *" member_list ", int *" member_list_entries ");
.SH DESCRIPTION
The
.B evs_membership_get
function is used to determine the current processors in the configuration and also
the local processor identifier.
The argument
.I handle
is used to reference the evs instantiation.
-The argument
+The argument
.I local_addr
will return the local address of the processor.
The argument
.I member_list
will return the list of processors in the current membership.
The argument
.I member_list_entries
should be set with the size of member_list and will return the size of the
member_list after return from the function.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR evs_overview (8),
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/evs_overview.8 b/man/evs_overview.8
index 581ecd3f..cb239da6 100644
--- a/man/evs_overview.8
+++ b/man/evs_overview.8
@@ -1,181 +1,181 @@
.\"/*
.\" * Copyright (c) 2004 MontaVista Software, 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.
.\" */
.TH EVS_OVERVIEW 8 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
The EVS library is delivered with the corosync project. This library is used
to create distributed applications that operate properly during partitions, merges,
and faults.
.PP
The library provides a mechanism to:
* handle abstraction for multiple instances of an EVS library in one application
* Deliver messages
* Deliver configuration changes
* join one or more groups
* leave one or more groups
* send messages to one or more groups
* send messages to currently joined groups
.PP
The EVS library implements a messaging model known as Extended Virtual Synchrony.
This model allows one sender to transmit to many receivers using standard UDP/IP.
UDP/IP is unreliable and unordered, so the EVS library applies ordering and reliability
to messages. Hardware multicast is used to avoid duplicated packets with two or more
receivers. Erroneous messages are corrected automatically by the library.
.PP
Certain guarantees are provided by the EVS library. These guarantees are related to
message delivery and configuration change delivery.
.SH DEFINITIONS
.TP
.B multicast
A multicast occurs when a network interface card sends a UDP packet to multiple
receivers simulatenously.
.TP
.B processor
A processor is the entity that executes the extended virtual synchrony algorithms.
.TP
.B configuration
A configuration is the current description of the processors executing the extended
virtual syncrhony algorithm.
.TP
.B configuration change
A configuration change occurs when a new configuration is delivered.
.TP
.B partition
A partition occurs when a configuration splits into two or more configurations, or
a processor fails or is stopped and leaves the configuration.
.TP
.B merge
A merge occurs when two or more configurations join into a larger new configuration. When
a new processor starts up, it is treated as a configuration with only one processor
and a merge occurs.
.TP
.B fifo ordering
A message is FIFO ordered when one sender and one receiver agree on the order of the
messages sent.
.TP
.B agreed ordering
A message is AGREED ordered when all processors agree on the order of the messages sent.
.TP
.B safe ordering
A message is SAFE ordered when all processors agree on the order of messages sent and
those messages are not delivered until all processors have a copy of the message to
deliver.
.TP
.B virtual syncrhony
Virtual syncrhony is obtained when all processors agree on the order of messages
sent and configuration changes sent for each new configuration.
.SH USING VIRTUAL SYNCHRONY
The virtual synchrony messaging model has many benefits for developing distributed
applications. Applications designed using replication have the most benefits. Applications
that must be able to partition and merge also benefit from the virtual synchrony messaging
model.
.PP
All applications receive a copy of transmitted messages even if there are errors on the
transmission media. This allows optimiziations when every processor must receive a copy
of the message for replication.
.PP
All messages are ordered according to agreed ordering. This mechanism allows the avoidance
-of race conditions. Consider a lock service implemented over several processors. Two
+of race conditions. Consider a lock service implemented over several processors. Two
requests occur at the same time on two seperate processors. The requests are ordered for
every processor in the same order and delivered to the processors. Then all processors
will get request A before request B and can reject request B. Any type of creation or
deletion of a shared data structure can benefit from this mechanism.
.PP
Self delivery ensures that messages that are sent by a processor are also delivered back
to that processor. This allows the processor sending the message to execute logic when
the message is self delivered according to agreed ordering and the virtual synchrony rules.
It also permits all logic to be placed in one message handler instead of two seperate places.
.PP
Virtual Synchrony allows the current configuration to be used to make decisions in partitions
and merges. Since the configuration is sent in the stream of messages to the application,
the application can alter its behavior based upon the configuration changes.
.SH ARCHITECTURE AND ALGORITHM
The EVS library is a thin IPC interface to the corosync executive. The corosync executive
provides services for the SA Forum AIS libraries as well as the EVS library.
.PP
The corosync executive uses a ring protocol and membership protocol to send messages
according to the semantics required by extended virtual synchrony. The ring protocol
creates a virtual ring of processors. A token is rotated around the ring of processors.
When the token is possessed by a processor, that processor may multicast messages to
other processors in the system.
.PP
The token is called the ORF token (for ordering, reliability, flow control). The ORF
token orders all messages by increasing a sequence number every time a message is
multicasted. In this way, an ordering is placed on all messages that all processors
agree to. The token also contains a retransmission list. If a token is received by
a processor that has not yet received a message it should have, a message sequence
number is added to the retransmission list. A processor that has a copy of the message
then retransmits the message. The ORF token provides configuration-wide flow control
by tracking the number of messages sent and limiting the number of messages that may
be sent by one processor on each posession of the token.
.PP
The membership protocol is responsible for ring formation and detecting when a processor
within a ring has failed. If the token fails to make a rotation within a timeout period
known as the token rotation timeout, the membership protocol will form a new ring.
If a new processor starts, it will also form a new ring. Two or more configurations
may be used to form a new ring, allowing many partitions to merge together into one
new configuration.
.SH PERFORMANCE
The EVS library obtains 8.5MB/sec throughput on 100 mbit network links with
many processors. Larger messages obtain better throughput results because the
time to access Ethernet is about the same for a small message as it is for a
larger message. Smaller messages obtain better messages per second, because the
time to send a message is not exactly the same.
.PP
80% of CPU utilization occurs because of encryption and authentication. The corosync
can be built without encryption and authentication for those with no security
requirements and low CPU utilization requirements. Even without encryption or
authentication, under heavy load, processor utilization can reach 25% on 1.5 GHZ
CPU processors.
.PP
The current corosync executive supports 16 processors, however, support for more processors is possible by changing defines in the corosync executive. This is untested, however.
.SH SECURITY
The EVS library encrypts all messages sent over the network using the SOBER-128
stream cipher. The EVS library uses HMAC and SHA1 to authenticate all messages.
The EVS library uses SOBER-128 as a pseudo random number generator. The EVS
library feeds the PRNG using the /dev/random Linux device.
.SH BUGS
This software is not yet production, so there may still be some bugs. But it appears
there are very few since nobody reports any unknown bugs at this point.
.SH "SEE ALSO"
.BR evs_initialize (3),
.BR evs_finalize (3),
.BR evs_fd_get (3),
.BR evs_dispatch (3),
.BR evs_join (3),
.BR evs_leave (3),
.BR evs_mcast_joined (3),
.BR evs_mcast_groups (3),
.BR evs_mmembership_get (3)
.PP
diff --git a/man/index.html b/man/index.html
index 755b3ba8..a4eb897f 100644
--- a/man/index.html
+++ b/man/index.html
@@ -1,226 +1,226 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-15">
<meta name="keywords" content="corosync, documentation, manual">
<meta name="author" content="many">
<meta name="copyright" content="&copy; 2009 Red Hat, Inc.">
<!-- meta http-equiv="Content-Style-Type" content="text/css" -->
<meta name="date" content="2009-03-17T13:50:00+01:00">
<title>Corosync Documentation</title>
</head>
<body>
<h1>Welcome to the corosync project's manual pages.</h1>
<p>
- <a href="corosync_overview.8.html">corosync_overview(8)</a>:
+ <a href="corosync_overview.8.html">corosync_overview(8)</a>:
Overview of the corosync system.
<br>
<a href="corosync.conf.5.html">corosync.conf(5)</a>:
Description of configuration options for corosync.
<br>
- <a href="evs_overview.8.html">evs_overview(8)</a>:
+ <a href="evs_overview.8.html">evs_overview(8)</a>:
Overview of the evs extended virtual synchrony group
- communication toolkit.
+ communication toolkit.
<br>
<a href="evs_initialize.3.html">evs_initialize(3)</a>:
Description of the evs_initialize interface.
<br>
- <a href="evs_finalize.3.html">evs_finalize(3)</a>:
+ <a href="evs_finalize.3.html">evs_finalize(3)</a>:
Description of the evs_finalize interface.
<br>
<a href="evs_dispatch.3.html">evs_dispatch(3)</a>:
Description of the evs_dispatch interface.
<br>
<a href="evs_fd_get.3.html">evs_fd_get(3)</a>:
Description of the evs_fd_get interface.
<br>
<a href="evs_join.3.html">evs_join(3)</a>:
Description of the evs_join interface.
<br>
<a href="evs_leave.3.html">evs_leave(3)</a>:
Description of the evs_leave interface.
<br>
<a href="evs_mcast_groups.3.html">evs_mcast_groups(3)</a>:
Description of the evs_mcast_groups interface.
<br>
<a href="evs_mcast_joined.3.html">evs_mcast_joined(3)</a>:
Description of the evs_mcast_joined interface.
<br>
<a href="evs_membership_get.3.html">evs_membership_get(3)</a>:
Description of the evs_membership_get interface.
<br>
<a href="cpg_overview.8.html">cpg_overview(8)</a>:
Overview of the cpg extended virtual synchrony group
- communication toolkit.
+ communication toolkit.
<br>
<a href="cpg_initialize.3.html">cpg_initialize(3)</a>:
Description of the cpg_initialize interface.
<br>
<a href="cpg_finalize.3.html">cpg_finalize(3)</a>:
Description of the cpg_finalize interface.
<br>
<a href="cpg_dispatch.3.html">cpg_dispatch(3)</a>:
Description of the cpg_dispatch interface.
<br>
<a href="cpg_fd_get.3.html">cpg_fd_get(3)</a>:
Description of the cpg_fd_get interface.
<br>
<a href="cpg_join.3.html">cpg_join(3)</a>:
Description of the cpg_join interface.
<br>
<a href="cpg_leave.3.html">cpg_leave(3)</a>:
Description of the cpg_leave interface.
<br>
<a href="cpg_mcast_joined.3.html">cpg_mcast_joined(3)</a>:
Description of the cpg_mcast_joined interface.
<br>
<a href="cpg_membership_get.3.html">cpg_membership_get(3)</a>:
Description of the cpg_membership_get interface.
<br>
<a href="cpg_local_get.3.html">cpg_local_get(3)</a>:
Description of the cpg_local_get interface.
<br>
<a href="cpg_groups_get.3.html">cpg_local_get(3)</a>:
Description of the cpg_groups_get interface.
<br>
<a href="confdb_overview.8.html">confdb_overview(8)</a>:
An overview of the Configuration database toolkit
<br>
<a href="confdb_dispatch.3.html">confdb_dispatch(3)</a>:
Description of the confdb_dispatch interface.
<br>
<a href="confdb_fd_get.3.html">confdb_fd_get(3)</a>:
Description of the confdb_fd_get interface.
<br>
<a href="confdb_finalize.3.html">confdb_finalize(3)</a>:
Description of the confdb_finalize interface.
<br>
<a href="confdb_initialize.3.html">confdb_initialize(3)</a>:
Description of the confdb_initialize interface.
<br>
<a href="confdb_key_create.3.html">confdb_key_create(3)</a>:
Description of the confdb_key_create interface.
<br>
<a href="confdb_key_delete.3.html">confdb_key_delete(3)</a>:
Description of the confdb_key_delete interface.
<br>
<a href="confdb_key_iter.3.html">confdb_key_iter(3)</a>:
Description of the confdb_key_iter interface.
<br>
<a href="confdb_key_replace.3.html">confdb_key_replace(3)</a>:
Description of the confdb_key_replace interface.
<br>
<a href="confdb_object_create.3.html">confdb_object_create(3)</a>:
Description of the confdb_object_create interface.
<br>
<a href="confdb_object_destroy.3.html">confdb_object_destroy(3)</a>:
Description of the confdb_object_destroy interface.
<br>
<a href="confdb_object_find.3.html">confdb_object_find(3)</a>:
Description of the confdb_object_find interface.
<br>
<a href="confdb_object_iter.3.html">confdb_object_iter(3)</a>:
Description of the confdb_object_iter interface.
<br>
<a href="confdb_object_parent_get.3.html">confdb_object_parent_get(3)</a>:
Description of the confdb_object_parent_get interface.
<br>
<a href="votequorum_overview.8.html">votequorum_overview(8)</a>:
An overview of the vote-based quorum service
<br>
<a href="votequorum_initialize.3.html">votequorum_initialize(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_finalize.3.html">votequorum_finalize(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_fd_get.3.html">votequorum_fd_get(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_getinfo.3.html">votequorum_getinfo(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_leaving.3.html">votequorum_leaving(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_setexpected.3.html">votequorum_setexpected(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_setvotes.3.html">votequorum_setvotes(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_qdisk_register.3.html">
votequorum_qdisk_register(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_qdisk_unregister.3.html">
votequorum_qdisk_unregister(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_qdisk_poll.3.html">votequorum_qdisk_poll(3)</a>:
Description of the votequorum interface.
<br>
<a href="votequorum_qdisk_getinfo.3.html">votequorum_qdisk_getinfo(3)</a>:
Description of the votequorum interface.
<br>
</body>
</html>
diff --git a/man/logsys_overview.8 b/man/logsys_overview.8
index 1358d10c..e39837a6 100644
--- a/man/logsys_overview.8
+++ b/man/logsys_overview.8
@@ -1,216 +1,216 @@
.\"/*
.\" * Copyright (c) 2007-2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Steven Dake (sdake@redhat.com)
.\" * Author: Fabio M. Di Nitto (fdinitto@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.
.\" */
.TH LOGSYS_OVERVIEW 8 2009-04-15 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
The logsys library provides a generically usable logging and tracing system for
use by applications. It supports many features including:
.PP
Configurable subsystem logging or single system logging
.PP
Threaded non-blocking logging of log output data for better non-blocking performance
.PP
Support for 8 tracing levels and tracing the entering and leaving of functions
.PP
Declaration of logging system or subsystem without calling any functions
.PP
Dynamic reconfiguration of the logging system parameters
.PP
Logging to syslog, file, stderr.
.SH Declaration of the System logger
The logsys library is initially configured by including logsys.h and declaring
a logger. Once the logger is declared, optional subsystem loggers can be
declared in every file.
The definition LOGSYS_DECLARE_SYSTEM is placed after the include section of one
C file in the application. This declaration creates a constructor function
which will be called automatically before main() is executed. This technique
avoids the need for calling any setup functions in short applications that don't
require it and enables full logging capabilities before any application code is
executed.
#define LOGSYS_DECLARE_SYSTEM (name, mode, debug, file, file_priority,
syslog_facility, syslog_priority, tags, format, rec_size)
The name parameter is the name of the application or system.
The mode parameter is the logging mode of the system.
The following modes can be configured by logically ORing these flags:
LOGSYS_MODE_OUTPUT_FILE: Output all log data to the file parameter of this declaration
LOGSYS_MODE_OUTPUT_STDERR: Output all log data to the stderr descriptor
LOGSYS_MODE_OUTPUT_SYSLOG: Output all log data to syslog using a non-blocking thread
LOGSYS_MODE_FORK: This flags tells logsys to queue all data untill the application
has forked. The application is then responsible to call logsys_fork_completed to flush
the queue and start logging.
LOGSYS_MODE_THREADED: Starts a separate thread to handle non-blocking logging operations.
If this flag is not specified, the logging operations are blocking.
The debug parameter, if enabled, turns off all messages priority filtering, recording
everything everywhere.
-The file parameter specifies the filename that should be used to log messages.
+The file parameter specifies the filename that should be used to log messages.
This parameter may be NULL and no log file will be created.
The file_priority parameter specifies the message priority that should be logged to file.
The syslog_facility parameter is the syslog facility that should be used when logging
messages.
The syslog_priority, similar to file_priority, specifies the message priority that should be logged to
syslog.
The tags parameter enables tracing by logically ORing these flags:
LOGSYS_TAG_ENTER
LOGSYS_TAG_LEAVE
LOGSYS_TAG_TRACE1 to LOGSYS_TAG_TRACE8
The format parameter allows to set custom output format.
Set to NULL to use built-in default.
The rec_size parameter specifies the flight recorder buffer size.
An example declaration would be:
#include <corosync/logsys.h>
... (other #includes)
LOGSYS_DECLARE_SYSTEM ("test", /* name */
LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_THREADED, /* mode */
0, /* debug */
NULL, /* logfile path */
LOGSYS_LEVEL_INFO, /* logfile_priority */
LOG_DAEMON, /* syslog facility */
LOGSYS_LEVEL_INFO, /* syslog level */
0, /* tags */
NULL, /* use default format */
1000000); /* flight recorder size */
.SH Declaration of subsystems
The logsys library supports the logging of information to one main system or
subsystem. This is specified in each individual object C file in the system
and it is entirely optional.
An example:
LOGSYS_DECLARE_SUBSYS ("subsystest");
-It is possible to use the same subsystem name in separate object files.
+It is possible to use the same subsystem name in separate object files.
In this case, the individual logging parameters for those subsystem identifier
will be used.
A newly created subsystem inherits the system configuration at the time of
creation.
It is possible to override every configuration option on a subsystem base
throught the configuration API.
.SH Logging Messages
The definition log_printf is used to log information to the log. It works
in a similiar fashion to printf, except it has a first parameter of level
which may be the following:
LOGSYS_LEVEL_EMERG
LOGSYS_LEVEL_ALERT
LOGSYS_LEVEL_CRIT
LOGSYS_LEVEL_ERR
LOGSYS_LEVEL_WARNING
LOGSYS_LEVEL_NOTICE
LOGSYS_LEVEL_INFO
LOGSYS_LEVEL_DEBUG
An example of using log_printf would be
log_printf (LOGSYS_LEVEL_EMERG, "This is an emergency %s value %d\n", string, value);
Tracing of functions can be done using ENTER_VOID() or ENTER (format, args) LEAVE_VOID() or LEAVE (format, args);
An exmaple of using ENTER_VOID is
void funtion (void) {
ENTER_VOID();
... function contents ...
LEAVE_VOID();
}
-An example of using ENTER is
+An example of using ENTER is
void function (char *name) {
ENTER ("The name is %s\n", name);
... function contents ...
LEAVE ("Bye\n");
}
Individual tracing levels are supported through the macros
TRACE1(format, args)
TRACE2(format, args)
..
TRACE8(format, args)
An example of using TRACE is
char *name = "test";
TRACE7 ("This is a trace 7 log with name %s\n", name);
.SH "SEE ALSO"
.BR logsys_fork_completed (3),
.BR logsys_atexit (3),
.BR logsys_log_rec_store (3),
.BR logsys_format_set (3),
.BR logsys_format_get (3),
.BR logsys_config_mode_set (3),
.BR logsys_config_file_set (3),
.BR logsys_config_syslog_facility_set (3),
.BR logsys_config_syslog_facility_get (3),
.BR logsys_config_mode_set (3),
.BR logsys_config_mode_get (3),
.BR logsys_config_tags_set (3),
.BR logsys_config_tags_get (3),
.BR logsys_config_file_set (3),
.BR logsys_config_logfile_priority_set (3),
.BR logsys_config_debug_set (3),
.BR logsys_facility_id_get (3),
.BR logsys_facility_name_get (3),
.BR logsys_priority_id_get (3),
.BR logsys_priority_name_get (3),
.BR logsys_tag_id_get (3),
.BR logsys_tag_name_get (3)
.PP
diff --git a/man/votequorum_dispatch.3 b/man/votequorum_dispatch.3
index e13aab67..c9e91f55 100644
--- a/man/votequorum_dispatch.3
+++ b/man/votequorum_dispatch.3
@@ -1,96 +1,96 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_DISPATCH 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_dispatch \- Dispatches callbacks from the votequorum service
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_dispatch(votequorum_handle_t " handle ", votequorum_dispatch_t *" dispatch_types ");"
.SH DESCRIPTION
The
.B votequorum_dispatch
function is used to dispatch configuration changes.
.PP
Each application may have several connections to the votequorum API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection.
.PP
The
.I dispatch_types
argument is used to identify the type of dispatch to execute. The possible types are
defined by the structure:
.IP
.RS
.ne 18
.nf
.ta 4n 30n 33n
typedef enum {
CS_DISPATCH_ONE,
CS_DISPATCH_ALL,
CS_DISPATCH_BLOCKING
} votequorum_dispatch_t;
.ta
.fi
.RE
.IP
.PP
.PP
The dispatch values have the following meanings:
.TP
.B CS_DISPATCH_ONE
Dispatch at least one callback, blocking until the callback is dispatched.
.TP
.B CS_DISPATCH_ALL
Dispatch all waiting callbacks without blocking to wait for any callbacks.
.TP
.B CS_DISPATCH_BLOCKING
Dispatch all callbacks blocking indefinitely. This is used in a threaded
program where a thread is created, and then votequorum_dispatch() is called immediately
from the created thread to execute callbacks.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_fd_get (3),
.PP
diff --git a/man/votequorum_fd_get.3 b/man/votequorum_fd_get.3
index 6dcc833e..2687bc3b 100644
--- a/man/votequorum_fd_get.3
+++ b/man/votequorum_fd_get.3
@@ -1,64 +1,64 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_FD_GET 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_fd_get \- Dispatches callbacks from the votequorum service
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_fd_get(votequorum_handle_t " handle ", int *" fd ");"
.SH DESCRIPTION
The
.B votequorum_fd_get
function is used to retrieve the file descriptor that may be used with the poll
system call to determine when
.B votequorum_dispatch(3)
won't block. The
.I handle
argument may not be used directly with
.B poll
because it is not the file descriptor, but instead an internal identifier used
by the votequorum library.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.PP
diff --git a/man/votequorum_finalize.3 b/man/votequorum_finalize.3
index 0fbc3e0d..c58aa892 100644
--- a/man/votequorum_finalize.3
+++ b/man/votequorum_finalize.3
@@ -1,61 +1,61 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_FINALIZE 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_finalize \- Terminate a connection to the votequorum service
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_finalize(votequorum_handle_t " handle ");"
.SH DESCRIPTION
The
.B votequorum_finalize
function is used to close a connection to the configuration dabatase API.
Once the connection is finalized, the handle may not be used again by applications.
No more callbacks will be dispatched from the
.B votequorum_dispatch function.
.PP
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.PP
diff --git a/man/votequorum_getinfo.3 b/man/votequorum_getinfo.3
index 7a06e636..99517e17 100644
--- a/man/votequorum_getinfo.3
+++ b/man/votequorum_getinfo.3
@@ -1,91 +1,91 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_GETINFO 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_getinfo \- Get information about the VoteQuorum service
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_getinfo(votequorum_handle_t *" handle ", unsigned int " nodeid ", struct votequorum_info *" info ");
.SH DESCRIPTION
The
.B votequorum_getinfo
-function is used to get information about the voteing system and its nodes.
+function is used to get information about the voteing system and its nodes.
The votequorum_info structure is defined as follows:
.PP
.PP
.IP
.RS
.ne 18
.nf
.ta 4n 20n 32n
struct votequorum_info {
unsigned int node_id;
unsigned int node_votes;
unsigned int node_expected_votes;
unsigned int highest_expected;
unsigned int total_votes;
unsigned int quorum;
unsigned int flags;
};
#define VOTEQUORUM_INFO_FLAG_DIRTY 1
#define VOTEQUORUM_INFO_FLAG_DISALLOWED 2
#define VOTEQUORUM_INFO_FLAG_TWONODE 4
#define VOTEQUORUM_INFO_FLAG_QUORATE 8
.ta
.fi
.RE
.IP
.PP
.PP
The members starting node_ hold information specific to the requested nodeid, the other are
general to the voting system.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH BUGS
Callbacks are not support at the moment.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_finalize (3),
.BR votequorum_fd_get (3),
.BR votequorum_dispatch (3),
.PP
diff --git a/man/votequorum_initialize.3 b/man/votequorum_initialize.3
index 2ea1c7fd..55548ebc 100644
--- a/man/votequorum_initialize.3
+++ b/man/votequorum_initialize.3
@@ -1,106 +1,106 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_INITIALIZE 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_initialize \- Create a new connection to the VoteQuorum service
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_initialize(votequorum_handle_t *" handle ", votequorum_callbacks_t *" callbacks ");
.SH DESCRIPTION
The
.B votequorum_initialize
function is used to initialize a connection to the vote-based quorum database API.
.PP
Each application may have several connections to the votequorum API. Each application
-uses the
+uses the
.I handle
argument to uniquely identify the connection. The
.I handle
argument is then used in other function calls to identify the connection to be used
for communication with the votequorum service.
.PP
Every time the voting configuraton changes (eg a node joins or leave the cluster), the callback is called.
The callback function is described by the following type definitions:
typedef void (*votequorum_notification_fn_t) (
votequorum_handle_t handle,
uint64_t context,
uint32_t quorate,
uint32_t node_list_entries,
votequorum_node_t node_list[]
);
.ta
.fi
.RE
.IP
.PP
.PP
The
.I callbacks
argument is of the type:
.IP
.RS
.ne 18
.nf
.PP
typedef struct {
votequorum_notification_fn_t votequorum_notify_fn;
} votequorum_callbacks_t;
.ta
.fi
.RE
.IP
.PP
When a configuration change occurs, the callback
is called from the
.B votequorum_dispatch()
-function.
+function.
.PP
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH BUGS
Callbacks are not support at the moment.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_finalize (3),
.BR votequorum_fd_get (3),
.BR votequorum_dispatch (3),
.PP
diff --git a/man/votequorum_leaving.3 b/man/votequorum_leaving.3
index 26aff114..ad7bda4a 100644
--- a/man/votequorum_leaving.3
+++ b/man/votequorum_leaving.3
@@ -1,67 +1,67 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_LEAVING 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_leaving \- Tell other nodes that we are leaving the cluster
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_leaving(votequorum_handle_t " handle ");"
.SH DESCRIPTION
The
.B votequorum_leaving
function is used to tell the other nodes in the cluster that this node is leaving. They
will (when the node actually leaves) reduce quorum to keep the cluster running without
this node.
.PP
This function should only be called if it is known that the node is being shut down for
-a known reason and could be out of the cluster for an extended period of time.
+a known reason and could be out of the cluster for an extended period of time.
.PP
Normal behaviour is for the cluster to reduce the total number of votes, but NOT expected_votes
when a node leave the cluster, so the cluster could become inquorate. This is correct behaviour
and is ther eto prevent split-brain.
.PP
Do NOT call this function unless you know what you are doing.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.PP
diff --git a/man/votequorum_overview.8 b/man/votequorum_overview.8
index 689e6318..b27e7aa9 100644
--- a/man/votequorum_overview.8
+++ b/man/votequorum_overview.8
@@ -1,82 +1,82 @@
.\"/*
.\" * Copyright (c) 2008 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
.\" * THE POSSIBILITY OF SUCH DAMAGE.
.\" */
.TH VOTEQUORUM_OVERVIEW 8 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH OVERVIEW
-The votequuorum library is delivered with the corosync project. It is the external interface to
+The votequuorum library is delivered with the corosync project. It is the external interface to
the vote-based quorum service. This service is optionally loaded into all ndes in a corosync cluster
to avoid split-brain situations. It does this by having a number of votes assigned to each system
in the cluster and ensuring that only when a majority of the votes are present, cluster operations are
allowed to proceed.
.PP
The library provides a mechanism to:
* Query the quorum status
.PP
* Get a list of nodes known to the quorum service
.PP
* Receive notifications of quorum state changes
.PP
* Change the number of votes assigned to a node
.PP
* Change the number of expected votes for a cluster to be quorate
.PP
* Connect an additional quorum device to allow small clusters to remain quorate during node outages.
.PP
-.B votequorum
+.B votequorum
reads its configuration from the objdb. The following keys are read when it starts up:
.PP
* quorum.expected_votes
.br
* quorum.votes
.br
* quorum.quorumdev_poll
.br
* quorum.disallowed
.br
* quorum.two_node
.PP
Most of those values can be changed while corosync is running with the following exceptions:
-.B quorum.disallowed
+.B quorum.disallowed
cannot be changed, and
.B two_node
cannot be set on-the-fly, though it can be cleared. ie you can start with two nodes in the cluster
and add a third without rebooting all the nodes.
.PP
.SH BUGS
This software is not yet production, so there may still be some bugs.
.SH "SEE ALSO"
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_fd_get (3),
.BR votequorum_dispatch (3),
.PP
diff --git a/man/votequorum_qdisk_getinfo.3 b/man/votequorum_qdisk_getinfo.3
index 10ee74d5..c3f1c535 100644
--- a/man/votequorum_qdisk_getinfo.3
+++ b/man/votequorum_qdisk_getinfo.3
@@ -1,80 +1,80 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_QDISK_GETINFO 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_qdisk_getinfo \- Get details of the quorum device
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_qdisk_getinfo(votequorum_handle_t " handle ", struct votequorum_qdisk_info " *info ");"
.SH DESCRIPTION
The
.B votequorum_qdisk_getinfo
Returns information about the quorum device in the following structure:
.PP
.PP
.IP
.RS
.ne 18
.nf
.ta 4n 20n 32n
struct votequorum_qdisk_info {
unsigned int votes;
unsigned int state;
char name[VOTEQUORUM_MAX_QDISK_NAME_LEN];
};
.ta
.fi
.RE
.IP
.PP
.PP
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.BR votequorum_qdisk_poll (3),
.BR votequorum_qdisk_unregister (3),
.BR votequorum_qdisk_getinfo (3),
.PP
diff --git a/man/votequorum_qdisk_poll.3 b/man/votequorum_qdisk_poll.3
index 52a9dd04..54780db5 100644
--- a/man/votequorum_qdisk_poll.3
+++ b/man/votequorum_qdisk_poll.3
@@ -1,69 +1,69 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_QDISK_POLL 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_qdisk_poll \- Tells votequorum the result of the quorum device poll
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_qdisk_poll(votequorum_handle_t " handle ", unsigned int " state ");"
.SH DESCRIPTION
The
.B votequorum_qdisk_poll
is called by the quorum device subsyetem (not provided as part of votequorum) to tell
-the voting system if the qurum device is present/active or not. If
+the voting system if the qurum device is present/active or not. If
.B state
is 1 then the votes for the device are included in the quorum calculation, otherwise not.
This routine should be called at regular intervals to ensure that the device status
-is always known to votequorum. If
+is always known to votequorum. If
.B votequorum_qdisk_poll
-is not called after (default) 10 seconds then the device will be deeded to be dead and
+is not called after (default) 10 seconds then the device will be deeded to be dead and
its votes removed from the cluster. This does not unregister the device.
The default poll time can be changed by setting the object database variable
quorum.quorumdev_poll.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.BR votequorum_qdisk_poll (3),
.BR votequorum_qdisk_unregister (3),
.BR votequorum_qdisk_getinfo (3),
.PP
diff --git a/man/votequorum_qdisk_register.3 b/man/votequorum_qdisk_register.3
index 20a067e9..a19c2f60 100644
--- a/man/votequorum_qdisk_register.3
+++ b/man/votequorum_qdisk_register.3
@@ -1,68 +1,68 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_QDISK_REGISTER 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_qdisk_register \- Registers a new quorum device
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_qdisk_register(votequorum_handle_t " handle ", char * " name ", unsigned int " votes ");"
.SH DESCRIPTION
The
.B votequorum_qdisk_register
-is used to register a new quorum device. A quorum device is an external way of adding votes to a small
+is used to register a new quorum device. A quorum device is an external way of adding votes to a small
cluster. The quorum device is, in effect, a pseudo node in the cluster that provide votes based on some
external device, usually a shared disk partition or perhaps a network router.
.br
This call creates the device but does not mark it active.
.B votequorum_qdisk_poll
must be called for the votes to be included in the quorum calculation.
.br
Note that it is the responsibility of the quorum device subsystem (not provided as part of votequorum)
to keep all nodes informed of the quorum device status.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.BR votequorum_qdisk_poll (3),
.BR votequorum_qdisk_unregister (3),
.BR votequorum_qdisk_getinfo (3),
.PP
diff --git a/man/votequorum_qdisk_unregister.3 b/man/votequorum_qdisk_unregister.3
index fde191ef..7d9dab0a 100644
--- a/man/votequorum_qdisk_unregister.3
+++ b/man/votequorum_qdisk_unregister.3
@@ -1,60 +1,60 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_QDISK_UNREGISTER 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_qdisk_unregister \- Unregisters a new quorum device
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_qdisk_unregister(votequorum_handle_t " handle ");"
.SH DESCRIPTION
The
.B votequorum_qdisk_unregister
unregisters a quorum device. Any votes it had will be removed from the cluster. Not that this could
make the cluster inquorate.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.BR votequorum_qdisk_poll (3),
.BR votequorum_qdisk_unregister (3),
.BR votequorum_qdisk_getinfo (3),
.PP
diff --git a/man/votequorum_setexpected.3 b/man/votequorum_setexpected.3
index c910921a..d33a6c98 100644
--- a/man/votequorum_setexpected.3
+++ b/man/votequorum_setexpected.3
@@ -1,60 +1,60 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_SETEXPECTED 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_setexpected \- Sets the expected votes for the cluster
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_setexpected(votequorum_handle_t " handle ", int " expected_votes ");"
.SH DESCRIPTION
The
.B votequorum_setexpected
function is used to change the expected votes in the cluster. Expected votes is used to calculate
quorum and should normally be the total number of votes that will exist when all the expected nodes
are joined. Quorum will usually be half of this (rounded up).
.br
It is not possible to set expected votes up so that it makes the cluster inquorate using this command.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.PP
diff --git a/man/votequorum_setvotes.3 b/man/votequorum_setvotes.3
index 9e3c1e0e..4fed319e 100644
--- a/man/votequorum_setvotes.3
+++ b/man/votequorum_setvotes.3
@@ -1,57 +1,57 @@
.\"/*
.\" * Copyright (c) 2009 Red Hat, Inc.
.\" *
.\" * All rights reserved.
.\" *
.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
.\" *
.\" * This software licensed under BSD license, the text of which follows:
-.\" *
+.\" *
.\" * Redistribution and use in source and binary forms, with or without
.\" * modification, are permitted provided that the following conditions are met:
.\" *
.\" * - Redistributions of source code must retain the above copyright notice,
.\" * this list of conditions and the following disclaimer.
.\" * - Redistributions in binary form must reproduce the above copyright notice,
.\" * this list of conditions and the following disclaimer in the documentation
.\" * and/or other materials provided with the distribution.
.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
.\" * contributors may be used to endorse or promote products derived from this
.\" * software without specific prior written permission.
.\" *
.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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.
.\" */
.TH VOTEQUORUM_VOTES 3 2009-01-26 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
.SH NAME
votequorum_setvotes \- Sets the number of votes for a node
.SH SYNOPSIS
.B #include <corosync/votequorum.h>
.sp
.BI "int votequorum_setexpected(votequorum_handle_t " handle ", unsigned int " nodeid ", int " votes ");"
.SH DESCRIPTION
The
.B votequorum_setvotes
-is used to change the number of votes that a node has. Note that it is not possible, using this function,
+is used to change the number of votes that a node has. Note that it is not possible, using this function,
to change the number of node votes such that the cluster goes inquorate.
.SH RETURN VALUE
This call returns the CS_OK value if successful, otherwise an error is returned.
.PP
.SH ERRORS
The errors are undocumented.
.SH "SEE ALSO"
.BR votequorum_overview (8),
.BR votequorum_initialize (3),
.BR votequorum_finalize (3),
.BR votequorum_dispatch (3),
.BR votequorum_fd_get (3),
.PP
diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am
index 4fb64471..828eaa9e 100644
--- a/pkgconfig/Makefile.am
+++ b/pkgconfig/Makefile.am
@@ -1,71 +1,71 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# All rights reserved.
-#
+#
# 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 ENGINES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
LIBS = cfg confdb coroipcc coroipcs cpg evs logsys pload quorum \
totem_pg votequorum
pkgconf_LIBS = $(LIBS:%=lib%)
target_LIBS = $(LIBS:%=lib%.pc)
target_PACKAGE = corosync.pc
lib%:
cat $(srcdir)/libtemplate.pc.in | sed \
-e 's#@PREFIX@#$(exec_prefix)#g' \
-e 's#@LIBDIR@#$(libdir)#g' \
-e 's#@LIBVERSION@#$(VERSION)#g' \
-e 's#@LIB@#'$(@:lib%=%)'#g' \
> $@.pc;
touch $@
$(target_PACKAGE):
cat $(srcdir)/$@.in | sed \
-e 's#@PREFIX@#$(exec_prefix)#g' \
-e 's#@LIBDIR@#$(libdir)#g' \
-e 's#@LIBVERSION@#$(VERSION)#g' \
-e 's#@COROLCRSODIR@#$(LCRSODIR)#g' \
-e 's#@COROSOCKETDIR@#$(SOCKETDIR)#g' \
> $@
all-local: $(pkgconf_LIBS) $(target_PACKAGE)
install-exec-local:
install -d $(DESTDIR)/$(libdir)/pkgconfig
install -m 644 $(target_LIBS) $(target_PACKAGE) $(DESTDIR)/$(libdir)/pkgconfig
uninstall-local:
cd $(DESTDIR)/$(libdir)/pkgconfig && rm -f $(target_LIBS) $(target_PACKAGE)
rmdir $(DESTDIR)/$(libdir)/pkgconfig 2> /dev/null || :
clean-local:
rm -f *.pc $(pkgconf_LIBS)
diff --git a/services/Makefile.am b/services/Makefile.am
index 3c7d289d..2d85f70a 100644
--- a/services/Makefile.am
+++ b/services/Makefile.am
@@ -1,86 +1,86 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
AM_CFLAGS = -fPIC
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \
-I$(top_builddir)/include/corosync \
-I$(top_srcdir)/include/corosync
SERVICE_LCRSO = evs cfg cpg confdb pload
QUORUM_LCRSO = votequorum testquorum
SOURCES = $(SERVICE_LCRSO:%=%.c) $(QUORUM_LCRSO:%=%.c)
EXTRA_DIST = $(SOURCES)
LCRSO = $(SERVICE_LCRSO:%=service_%.lcrso) $(QUORUM_LCRSO:%=quorum_%.lcrso)
LCRSO_OBJS = $(SOURCES:%.c=%.o)
if BUILD_DARWIN
quorum_%.lcrso: %.o
$(CC) $(CFLAGS) -bundle -bundle_loader ../exec/corosync $^ -o $@
service_%.lcrso: %.o
$(CC) $(CFLAGS) -bundle -bundle_loader ../exec/corosync $^ -o $@
else
quorum_%.lcrso: %.o
$(CC) $(CFLAGS) -shared -Wl,-soname=$@ $^ -o $@
service_%.lcrso: %.o
$(CC) $(CFLAGS) -shared -Wl,-soname=$@ $^ -o $@
endif
%.o: %.c
$(CC) $(AM_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c -o $@ $<
lint:
-splint $(LINT_FLAGS) $(CFLAGS) *.c
all-local: $(LCRSO_OBJS) $(LCRSO)
@echo Built Service Engines
install-exec-local:
$(INSTALL) -d $(DESTDIR)/$(LCRSODIR)
$(INSTALL) -m 755 $(LCRSO) $(DESTDIR)/$(LCRSODIR)
uninstall-local:
cd $(DESTDIR)/$(LCRSODIR) && \
rm -f $(LCRSO)
clean-local:
rm -f *.o *.a *.so* *.da *.bb *.bbg *.lcrso
diff --git a/test/Makefile.am b/test/Makefile.am
index a9e3f29c..783c38a5 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,79 +1,79 @@
#
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
noinst_PROGRAMS = testevs evsbench evsverify testcpg testcpg2 cpgbench testconfdb \
logsysbench logsysrec testquorum testvotequorum1 testvotequorum2 \
logsys_s logsys_t1 logsys_t2 testcpgzc cpgbenchzc testzcgc
testevs_LDADD = -levs
testevs_LDFLAGS = -L../lib
testcpg_LDADD = -lcpg
testcpg_LDFLAGS = -L../lib
testcpg2_LDADD = -lcpg
testcpg2_LDFLAGS = -L../lib
testcpgzc_LDADD = -lcpg
testcpgzc_LDFLAGS = -L../lib
testzcgc_LDADD = -lcpg
testzcgc_LDFLAGS = -L../lib
testconfdb_LDADD = -lconfdb ../lcr/liblcr.a
testconfdb_LDFLAGS = -L../lib
testquorum_LDADD = -lquorum
testquorum_LDFLAGS = -L../lib
testvotequorum1_LDADD = -lvotequorum
testvotequorum1_LDFLAGS = -L../lib
testvotequorum2_LDADD = -lvotequorum
testvotequorum2_LDFLAGS = -L../lib
evsverify_LDADD = -levs -ltotem_pg
evsverify_LDFLAGS = -L../lib -L../exec
evsbench_LDADD = -levs
evsbench_LDFLAGS = -L../lib
cpgbench_LDADD = -lcpg
cpgbench_LDFLAGS = -L../lib
cpgbenchzc_LDADD = -lcpg
cpgbenchzc_LDFLAGS = -L../lib
logsysbench_LDADD = -llogsys
logsysbench_LDFLAGS = -L../exec
logsysrec_LDADD = -llogsys
logsysrec_LDFLAGS = -L../exec
logsys_s_SOURCES = logsys_s.c logsys_s1.c logsys_s2.c
logsys_s_LDADD = -llogsys
logsys_s_LDFLAGS = -L../exec
logsys_t1_LDADD = -llogsys
logsys_t1_LDFLAGS = -L../exec
logsys_t2_LDADD = -llogsys
logsys_t2_LDFLAGS = -L../exec
lint:
-splint $(LINT_FLAGS) $(CFLAGS) *.c
diff --git a/test/logsys_s.c b/test/logsys_s.c
index 0979af4d..76237182 100644
--- a/test/logsys_s.c
+++ b/test/logsys_s.c
@@ -1,61 +1,61 @@
/*
* Copyright (c) 2007 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <syslog.h>
#include <corosync/engine/logsys.h>
LOGSYS_DECLARE_SYSTEM ("logsystestsubsystems",
LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_OUTPUT_SYSLOG,
0,
NULL,
LOGSYS_LEVEL_INFO,
LOG_DAEMON,
LOGSYS_LEVEL_INFO,
0,
NULL,
1000000);
extern void logsys_s1_print (void);
extern void logsys_s2_print (void);
int main (void) {
logsys_fork_completed();
logsys_s1_print();
logsys_s2_print();
return (0);
}
diff --git a/test/logsys_s1.c b/test/logsys_s1.c
index 07bb1846..296b189e 100644
--- a/test/logsys_s1.c
+++ b/test/logsys_s1.c
@@ -1,49 +1,49 @@
/*
* Copyright (c) 2007 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <syslog.h>
#include <corosync/engine/logsys.h>
void logsys_s1_print (void);
LOGSYS_DECLARE_SUBSYS ("SYS1");
void logsys_s1_print (void) {
log_printf (LOGSYS_LEVEL_ALERT, "This is an alert log message\n");
log_printf (LOGSYS_LEVEL_WARNING, "This is a warning log message\n");
}
diff --git a/test/logsys_s2.c b/test/logsys_s2.c
index e5d68bc4..a680ad96 100644
--- a/test/logsys_s2.c
+++ b/test/logsys_s2.c
@@ -1,51 +1,51 @@
/*
* Copyright (c) 2007 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <syslog.h>
#include <corosync/engine/logsys.h>
void logsys_s2_print (void);
LOGSYS_DECLARE_SUBSYS ("SYS2");
void logsys_s2_print (void) {
logsys_config_logfile_priority_set("SYS2", LOGSYS_LEVEL_DEBUG);
log_printf (LOGSYS_LEVEL_ALERT, "This is an alert log message\n");
log_printf (LOGSYS_LEVEL_WARNING, "This is a warning log message\n");
log_printf (LOGSYS_LEVEL_DEBUG, "This is a debug log message\n");
}
diff --git a/test/logsys_t1.c b/test/logsys_t1.c
index fb5476f1..58240ffa 100644
--- a/test/logsys_t1.c
+++ b/test/logsys_t1.c
@@ -1,58 +1,58 @@
/*
* Copyright (c) 2007 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <syslog.h>
#include <corosync/engine/logsys.h>
LOGSYS_DECLARE_SYSTEM ("logsystestNOsubsystems",
- LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_OUTPUT_SYSLOG,
+ LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_OUTPUT_SYSLOG,
0,
NULL,
LOGSYS_LEVEL_DEBUG,
LOG_DAEMON,
LOGSYS_LEVEL_DEBUG,
0,
NULL,
1000000);
int main (void) {
log_printf (LOGSYS_LEVEL_ALERT, "This is an alert log message\n");
log_printf (LOGSYS_LEVEL_WARNING, "This is a warning log message\n");
log_printf (LOGSYS_LEVEL_DEBUG, "This is a debug log message\n");
return (0);
}
diff --git a/test/logsys_t2.c b/test/logsys_t2.c
index 9960a4ed..c720a5be 100644
--- a/test/logsys_t2.c
+++ b/test/logsys_t2.c
@@ -1,84 +1,84 @@
/*
* Copyright (c) 2007 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Lon Hohberger (lhh@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <stdint.h>
#include <corosync/engine/logsys.h>
LOGSYS_DECLARE_SYSTEM ("logtest_t2",
LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_THREADED,
0,
NULL,
LOGSYS_LEVEL_INFO,
LOG_DAEMON,
LOGSYS_LEVEL_INFO,
0,
NULL,
1000000);
int
main(int argc, char **argv)
{
/*
* fork could occur here and the file to output to could be set
*/
logsys_config_mode_set (NULL, LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_THREADED);
log_printf(LOGSYS_LEVEL_NOTICE, "Hello, world!\n");
log_printf(LOGSYS_LEVEL_DEBUG, "If you see this, the logger's busted\n");
logsys_config_logfile_priority_set (NULL, LOGSYS_LEVEL_ALERT);
log_printf(LOGSYS_LEVEL_DEBUG, "If you see this, the logger's busted\n");
log_printf(LOGSYS_LEVEL_CRIT, "If you see this, the logger's busted\n");
log_printf(LOGSYS_LEVEL_ALERT, "Alert 1\n");
logsys_config_logfile_priority_set (NULL, LOGSYS_LEVEL_NOTICE);
log_printf(LOGSYS_LEVEL_CRIT, "Crit 1\n");
log_printf(LOGSYS_LEVEL_INFO, "If you see this, the logger's busted\n");
logsys_config_logfile_priority_set (NULL, LOGSYS_LEVEL_DEBUG);
log_printf(LOGSYS_LEVEL_DEBUG, "Debug 1\n");
logsys_config_mode_set (NULL, LOGSYS_MODE_OUTPUT_STDERR);
log_printf(LOGSYS_LEVEL_DEBUG, "Debug 2\n");
return 0;
}
diff --git a/test/logsysrec.c b/test/logsysrec.c
index 65ab9452..c621f406 100644
--- a/test/logsysrec.c
+++ b/test/logsysrec.c
@@ -1,67 +1,67 @@
/*
* 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.
*/
#include <config.h>
#include <stdio.h>
#include <stdint.h>
#include <corosync/engine/logsys.h>
LOGSYS_DECLARE_SYSTEM ("logtest_rec",
LOGSYS_MODE_OUTPUT_STDERR | LOGSYS_MODE_THREADED,
0,
NULL,
LOG_INFO,
LOG_DAEMON,
LOG_INFO,
0,
NULL,
100000);
#define LOGREC_ID_CHECKPOINT_CREATE 2
#define LOGREC_ARGS_CHECKPOINT_CREATE 2
int main(int argc, char **argv)
{
int i;
for (i = 0; i < 10; i++) {
log_printf (LOGSYS_LEVEL_NOTICE, "This is a test of %s\n", "stringparse");
log_rec (LOGREC_ID_CHECKPOINT_CREATE, "record1", 8, "record22", 9, "record333", 10, "record444", 11, LOGSYS_REC_END);
}
logsys_log_rec_store ("fdata");
return 0;
}
diff --git a/test/sa_error.c b/test/sa_error.c
index c0dc6f2e..679601c7 100644
--- a/test/sa_error.c
+++ b/test/sa_error.c
@@ -1,67 +1,67 @@
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "saAis.h"
const char *sa_error_list[] = {
"OUT_OF_RANGE",
"CS_OK",
"CS_ERR_LIBRARY",
"CS_ERR_VERSION",
"CS_ERR_INIT",
"CS_ERR_TIMEOUT",
"CS_ERR_TRY_AGAIN",
"CS_ERR_INVALID_PARAM",
"CS_ERR_NO_MEMORY",
"CS_ERR_BAD_HANDLE",
"CS_ERR_BUSY",
"CS_ERR_ACCESS",
"CS_ERR_NOT_EXIST",
"CS_ERR_NAME_TOO_LONG",
"CS_ERR_EXIST",
"CS_ERR_NO_SPACE",
"CS_ERR_INTERRUPT",
"CS_ERR_NAME_NOT_FOUND",
"CS_ERR_NO_RESOURCES",
"CS_ERR_NOT_SUPPORTED",
"CS_ERR_BAD_OPERATION",
"CS_ERR_FAILED_OPERATION",
"CS_ERR_MESSAGE_ERROR",
"CS_ERR_QUEUE_FULL",
"CS_ERR_QUEUE_NOT_AVAILABLE",
"CS_ERR_BAD_CHECKPOINT",
"CS_ERR_BAD_FLAGS",
"CS_ERR_NO_SECTIONS",
};
int get_sa_error(cs_error_t error, char *str, int len)
{
- if (error < CS_OK ||
- error > CS_ERR_NO_SECTIONS ||
+ if (error < CS_OK ||
+ error > CS_ERR_NO_SECTIONS ||
len < strlen(sa_error_list[error])) {
errno = EINVAL;
return -1;
}
strncpy(str, sa_error_list[error], len);
return 0;
}
char *get_sa_error_b (cs_error_t error) {
return ((char *)sa_error_list[error]);
}
char *get_test_output (cs_error_t result, cs_error_t expected) {
static char test_result[256];
if (result == expected) {
return ("PASSED");
} else {
snprintf (test_result, sizeof(test_result),
"FAILED expected %s got %s",
get_sa_error_b(expected), get_sa_error_b(result));
return (test_result);
}
}
diff --git a/test/testevsth.c b/test/testevsth.c
index 9a1635d9..9f8e5f65 100644
--- a/test/testevsth.c
+++ b/test/testevsth.c
@@ -1,186 +1,186 @@
/*
* Copyright (c) 2004 MontaVista Software, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <pthread.h>
#include "../include/evs.h"
char *delivery_string;
#define CALLBACKS 200000
int callback_count = 0;
void evs_deliver_fn (struct in_addr source_addr, const void *msg, size_t msg_len)
{
#ifdef PRINT_OUTPUT
char *buf;
buf += 100000;
printf ("Delivery callback\n");
printf ("callback %d '%s' msg '%s'\n", callback_count, delivery_string, buf);
#endif
callback_count += 1;
if (callback_count % 50 == 0) {
printf ("Callback %d\n", callback_count);
}
}
void evs_confchg_fn (
const struct in_addr *member_list, size_t member_list_entries,
const struct in_addr *left_list, size_t left_list_entries,
const struct in_addr *joined_list, size_t joined_list_entries)
{
int i;
printf ("CONFIGURATION CHANGE\n");
printf ("--------------------\n");
printf ("New configuration\n");
for (i = 0; i < member_list_entries; i++) {
printf ("%s\n", inet_ntoa (member_list[i]));
}
printf ("Members Left:\n");
for (i = 0; i < left_list_entries; i++) {
printf ("%s\n", inet_ntoa (left_list[i]));
}
printf ("Members Joined:\n");
for (i = 0; i < joined_list_entries; i++) {
printf ("%s\n", inet_ntoa (joined_list[i]));
}
}
evs_callbacks_t callbacks = {
evs_deliver_fn,
evs_confchg_fn
};
struct evs_group groups[3] = {
{ "key1" },
{ "key2" },
{ "key3" }
};
char buffer[1000];
struct iovec iov = {
.iov_base = buffer,
.iov_len = sizeof (buffer)
};
void *th_dispatch (void *arg)
{
evs_error_t result;
evs_handle_t handle = *(evs_handle_t *)arg;
printf ("THREAD DISPATCH starting.\n");
result = evs_dispatch (handle, EVS_DISPATCH_BLOCKING);
printf ("THREAD DISPATCH return result is %d\n", result);
return (0);
}
static struct sched_param sched_param = {
sched_priority: 99
};
int main (void)
{
evs_handle_t handle;
evs_error_t result;
int i = 0;
pthread_t dispatch_thread;
pthread_attr_t dispatch_thread_attribute;
result = evs_initialize (&handle, &callbacks);
if (result != EVS_OK) {
printf ("Couldn't initialize EVS service %d\n", result);
exit (0);
}
pthread_attr_init (&dispatch_thread_attribute);
pthread_attr_setschedpolicy (&dispatch_thread_attribute, SCHED_FIFO);
pthread_attr_setschedparam (&dispatch_thread_attribute, &sched_param);
pthread_create (&dispatch_thread, NULL, th_dispatch, &handle);
printf ("Init result %d\n", result);
result = evs_join (handle, groups, 3);
printf ("Join result %d\n", result);
result = evs_leave (handle, &groups[0], 1);
printf ("Leave result %d\n", result);
delivery_string = "evs_mcast_joined";
/*
* Demonstrate evs_mcast_joined
*/
for (i = 0; i < CALLBACKS/2; i++) {
sprintf (buffer, "evs_mcast_joined: This is message %d", i);
try_again_one:
result = evs_mcast_joined (handle, EVS_TYPE_AGREED, &iov, 1);
if (result == EVS_ERR_TRY_AGAIN) {
goto try_again_one;
} else
if (result != EVS_OK) {
printf ("Got error result, exiting %d\n", result);
exit (1);
}
}
/*
* Demonstrate evs_mcast_joined
*/
delivery_string = "evs_mcast_groups";
for (i = 0; i < CALLBACKS/2; i++) {
sprintf (buffer, "evs_mcast_groups: This is message %d", i);
try_again_two:
result = evs_mcast_groups (handle, EVS_TYPE_AGREED,
&groups[1], 1, &iov, 1);
if (result == EVS_ERR_TRY_AGAIN) {
goto try_again_two;
}
}
/*
* Wait until all callbacks have been executed by dispatch thread
*/
for (;;) {
if (callback_count == CALLBACKS) {
printf ("Test completed successfully\n");
exit (0);
}
}
return (0);
}
diff --git a/test/testmake.sh b/test/testmake.sh
index 47f6c981..da7ade3b 100644
--- a/test/testmake.sh
+++ b/test/testmake.sh
@@ -1,115 +1,115 @@
#!/bin/sh
#
# author: Angus Salkeld (ahsalkeld@gmail.com)
#
# usage:
# run this from the base directory of corosync
#
SRCDIR=$(pwd)
ALL_TESTS="1 2 3 4"
MAKE_LOG=/tmp/corosync-make-test.log
test_1()
{
TEST="[1] simple make"
rm -f $SRCDIR/make_o_path
make >$MAKE_LOG 2>&1
return $?
}
make_clean()
{
if [ -f $SRCDIR/make_o_path ]
then
make $(cat $SRCDIR/make_o_path) clean >$MAKE_LOG 2>&1
RES=$?
else
if [ -n "$BUILD_DIR" ]
then
pushd $BUILD_DIR >/dev/null
make -f $SRCDIR/Makefile clean >$MAKE_LOG 2>&1
RES=$?
popd >/dev/null
else
make clean >$MAKE_LOG 2>&1
RES=$?
fi
fi
return $RES
}
test_2()
{
rm -f $SRCDIR/make_o_path
TEST="[2] make from exec dir"
pushd $SRCDIR/exec >/dev/null
make >$MAKE_LOG 2>&1
RES=$?
popd >/dev/null
return $RES
}
test_3()
{
local BUILD_DIR=/tmp/corosync-make-test
echo "O=$BUILD_DIR" > $SRCDIR/make_o_path
TEST="[3] make objects separately from the source"
rm -rf $BUILD_DIR
make O=$BUILD_DIR >$MAKE_LOG 2>&1
unset BUILD_DIR
return $?
}
test_4()
{
BUILD_DIR=/tmp/corosync-make-test
rm -f $SRCDIR/make_o_path
TEST="[4] make -f SRCDIR/Makefile from the builddir"
-
+
rm -rf $BUILD_DIR
mkdir -p $BUILD_DIR
pushd $BUILD_DIR >/dev/null
make -f $SRCDIR/Makefile >$MAKE_LOG 2>&1
RES=$?
popd >/dev/null
return $RES
}
if [ -n "$1" ]
then
TESTS_TO_RUN=$1
else
TESTS_TO_RUN=$ALL_TESTS
fi
for t in $TESTS_TO_RUN
do
test_$t
if [ $? -ne 0 ]
then
echo "$0 $TEST [failed]."
cat $MAKE_LOG
exit 1
else
echo "$0 $TEST [passed]."
fi
make_clean
if [ $? -ne 0 ]
then
echo "$0 $TEST [failed to clean]."
cat $MAKE_LOG
exit 1
else
echo "$0 $TEST [cleaned]."
fi
done
echo $0 all make tests passed!
exit 0
diff --git a/test/testparse.c b/test/testparse.c
index 5ddefc64..ef7f3cca 100644
--- a/test/testparse.c
+++ b/test/testparse.c
@@ -1,58 +1,58 @@
/*
* Copyright (c) 2002-2004 MontaVista Software, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "../include/saAis.h"
#include "../exec/parse.h"
#include "../exec/print.h"
int main (void)
{
#ifdef CODE_COVERAGE_COMPILE_OUT
int result;
int error;
result = amfReadGroups (&error);
if (result == -1) {
printf ("Parse Error: %s\n", error);
exit (-1);
}
-
+
saAmfPrintGroups ();
#endif
return (0);
}
diff --git a/test/testtimer.c b/test/testtimer.c
index 36416d8d..7cbbe7c4 100644
--- a/test/testtimer.c
+++ b/test/testtimer.c
@@ -1,78 +1,78 @@
/*
* Copyright (c) 2003-2004 MontaVista Software, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/poll.h>
#include "../exec/timer.h"
void timer_function (void *data)
{
printf ("timer %p\n", data);
-}
+}
int main (void)
{
int msec;
struct timer *timer;
int randomvalue;
int i;
printf ("adding timers\n");
for (i = 0; i < 1000; i++) {
timer = (struct timer *)malloc (sizeof (struct timer));
randomvalue = random()%5000;
timer->function = timer_function;
timer->data = (void *)randomvalue;
timer_add_msec_in_future (timer, randomvalue);
}
printf ("done adding timers\n");
for (;;) {
msec = timer_expire_get_msec();
// printf ("msec to next timer expire %d\n", msec);
if (msec == -1) {
printf ("no more timers\n");
break;
}
poll (0, 0, msec);
timer_expire ();
}
return (0);
}
diff --git a/tools/Makefile.am b/tools/Makefile.am
index d56468b4..3a1973b8 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,47 +1,47 @@
# Copyright (c) 2009 Red Hat, Inc.
-#
+#
# Authors: Andrew Beekhof
# Steven Dake (sdake@redhat.com)
#
# This software licensed under BSD license, the text of which follows:
-#
+#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
-#
+#
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# - Neither the name of the MontaVista Software, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
sbin_PROGRAMS = corosync-fplay corosync-cfgtool \
corosync-keygen corosync-objctl \
corosync-pload
corosync_pload_LDADD = ../lib/libpload.a
-corosync_objctl_LDADD = ../lib/libconfdb.a ../lcr/liblcr.a
+corosync_objctl_LDADD = ../lib/libconfdb.a ../lcr/liblcr.a
corosync_cfgtool_LDADD = ../lib/libcfg.a
lint:
-splint $(LINT_FLAGS) $(CFLAGS) *.c
diff --git a/tools/corosync-pload.c b/tools/corosync-pload.c
index d75ba091..c92801bd 100644
--- a/tools/corosync-pload.c
+++ b/tools/corosync-pload.c
@@ -1,78 +1,78 @@
/*
- * Copyright (c) 2008 Red Hat, Inc.
+ * Copyright (c) 2008-2009 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Steven Dake (sdake@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <corosync/corotypes.h>
#include <corosync/pload.h>
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
int main (void) {
pload_error_t result;
pload_handle_t handle;
result = pload_initialize (&handle, NULL);
printf ("Init result %d\n", result);
result = pload_start (
handle,
0, /* code */
1500000, /* count */
300); /* size */
return (0);
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Feb 24, 1:53 PM (7 h, 5 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1457281
Default Alt Text
(1 MB)

Event Timeline