From 95f17845c6b8ba45dcd2df14845de7031b332971 Mon Sep 17 00:00:00 2001 From: John Cherry Date: Tue, 15 Jun 2004 22:18:04 +0000 Subject: [PATCH] (Logical change 1.3) git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@5 fd59a12c-fef9-0310-b244-a6a79926bd2f --- CHANGELOG | 232 ++++ LICENSE | 29 + Makefile | 51 + Makefile.samples | 63 + QUICKSTART | 107 ++ README.devmap | 169 +++ TODO | 67 + conf/groups.conf | 58 + conf/network.conf | 3 + exec/Makefile | 55 + exec/amf.c | 2176 ++++++++++++++++++++++++++++++++ exec/amf.h | 56 + exec/ckpt.c | 1638 +++++++++++++++++++++++++ exec/ckpt.h | 81 ++ exec/clm.c | 456 +++++++ exec/clm.h | 51 + exec/gmi.c | 2861 +++++++++++++++++++++++++++++++++++++++++++ exec/gmi.h | 85 ++ exec/handlers.h | 59 + exec/log/print.c | 90 ++ exec/log/print.h | 64 + exec/main.c | 722 +++++++++++ exec/main.h | 113 ++ exec/mempool.c | 224 ++++ exec/mempool.h | 57 + exec/parse.c | 444 +++++++ exec/parse.h | 161 +++ exec/poll.c | 477 ++++++++ exec/poll.h | 78 ++ exec/print.c | 171 +++ exec/print.h | 65 + exec/profile | 560 +++++++++ exec/tlist.c | 247 ++++ exec/tlist.h | 62 + include/ais_amf.h | 221 ++++ include/ais_ckpt.h | 174 +++ include/ais_clm.h | 100 ++ include/ais_msg.h | 728 +++++++++++ include/ais_types.h | 394 ++++++ include/list.h | 75 ++ include/queue.h | 163 +++ include/sq.h | 185 +++ init/ais | 28 + lib/Makefile | 56 + lib/amf.c | 938 ++++++++++++++ lib/ckpt.c | 1251 +++++++++++++++++++ lib/clm.c | 476 +++++++ lib/util.c | 564 +++++++++ lib/util.h | 186 +++ loc | 14 + test/Makefile | 92 ++ test/ckptstress.c | 200 +++ test/scripts/spam | 999 +++++++++++++++ test/scripts/spam2 | 82 ++ test/testamf.c | 315 +++++ test/testamf1.c | 276 +++++ test/testamf2.c | 305 +++++ test/testamf3.c | 266 ++++ test/testamf4.c | 265 ++++ test/testamf5.c | 266 ++++ test/testamf6.c | 266 ++++ test/testamfth.c | 280 +++++ test/testckpt.c | 347 ++++++ test/testclm.c | 191 +++ test/testparse.c | 54 + test/testtimer.c | 75 ++ 66 files changed, 21664 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index e69de29b..42872701 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -0,0 +1,232 @@ +Application Interface Specification Implementation +-------------------------------------------------- +0.30 +* Add GMI & sort queues to build environment. +* Changed queue.h to be more consistent with naming conventions used in tree. +* Simplified cluster membmership service by modifying to use GMI. +* Modified availability management framework to use GMI. +* Modified method services connect to main executive to make services standalone + objects. This could facilitate plugin services in the future. +* Modified checkpointing for multinode using GMI. +* healthcheck timeouts were being caused by slow access to the filesystem for + sockets and deleted sockets. This was fixed by using the abstract namespace + which is memory based. +* Generic logging facility added to get rid of numerous #ifdef DEBUGs and avoid + the SIGPIPE and signal changes created by the libc's version of syslog. +* Authentication for API<->executive added. Only uid=0 or gid=ais processes can + connect to the executive via the libraries to provide service. +* This release has alot of cleanups! +* Removed all point-to-point authentication since using GMI now. + +* GMI provides extended virtual synchrony semantics with: +* - agreed message ordering (all processors agree on message order) +* - using available hardware multicast +* - group membership algorithm that currently supports 16 processors +* - message fragmentation to fit MTU that avoids UDP fragmentation +* - full recovery of messages during configuration change +* - 512kb message support +* - 3 priority levels + +0.29 +* Changed all send/recv functions to sendmsg/recvmsg. + +0.28 +* Remove current poll code and replace with poll abstraction. + +0.27 +* Add CKPT service to AIS Executive for single node checkpointing. + +0.26 +* Added support for pthreads to clm and amf interfaces. Critical + sections and shared data now protected by mutex. If Dispatch in + one thread, Finalize in another thread will cause Dispatch to behave + per spec. +* Moved global receive buffer for APIs into handles or stack. +* Allocate and free instance memory in handle manager instead of in each API. +* Merge defect fixes from 0.22.1-0.22.8 into development tree. +* CkptCheckpointHandleT and CkptSectionIteratorT functions created a new + connection each time any APIs using those types were called. Now these + types have been encapsulated into their own handle database which doesn't + create (expensive) connections for each API call. +* Changed named types such as MESSAGE_CKPT_REQ* to MESSAGE_REQ_CKPT* to match + structure names. + +0.25 +* Added ability for authentication to use none, password, or DSA depending on + settings in file /etc/ais/authtype. The values are no authentication, password + authentication, or dsa authentication. +* Added DSA authentication to node-to-node communication. + Server generates 16 byte random number, sends random number to connecting + client, client signs random number message with DSA private key, server + verifies signature with public key of client for random number message. +* Added DSA key generator. +* Added password authentication. File /etc/ais/aiskeys/password is used by the + server to compare the client's password. If they match, the connection is + authenticated. +* Added no authentication option. +* Fixed PPC compile to compile cleanly with -Wall. +* Added version checking to APIs. + +0.24 +* Fixed problem if outbound queues have messages queued, they are not + sent during the poll loop because poll isn't passed the correct events flag. + This problem introduced in the select to poll conversion in 0.23. +* Healthchecks for CLM service intra-node now run on seperate timers per connection. +* Fixed problem connections intra-node were completely broken as a result + of the change from select to poll in 0.23. +* Fixed bug in AMF timer_del on NULL timer. +* Fixed few bugs in AMF intra-node communications would result in segfault. +* Made pollfd_table global to reduce variable passing and simplify code. +* Cleaned up with compile of -Wall which found several bugs. +* Some minor cleanups of makefiles from major reorg in 0.23. +* Replaced memory malloc/free/realloc with memory pool versions to avoid + failed memory allocation requests and improve realtime response. +* Implemented the library portion of all checkpointing (Ckpt) APIs. + +0.23 +* Reorganized executive into exec directory and split executive components + into seperate files. +* Placed library interfaces into lib directory. +* Placed test components into test directory. +* Abstracted some of the service setup and teardown code that was + integrated into the main loops and disconnect function call to call + generic functions {amf|clm}InitializeExecutive, and {amf|clm}FinalizeApi. +* Cleaned up connection (ci) datatypes. +* Removed old timers, replaced with generic timer implementation. +* replaced select with poll in executive. +* lock memory of process and set RR prio 99 to avoid priority inversions. +* Fixed problem where accept couldn't connect because resource exhaustion, + executive would crash. + +0.22 +* Fix defect in HA state and operational state machines where states are not + always determined correctly. +* Fix defect invalid argument to saAmfErrorReport will crash executive. +* Fix defect no /var/run/aisexec.pid created for service. + +0.21 +* Fix defect testclm doesn't exit if no connection to AIS executive possible. +* Fix defect aisexec crashes if no /etc/groups.conf file present. +* Fix defect aisexec opens "groups.conf" instead of "/etc/groups.conf" file. +* Fix defect aisexec doesn't set SaClmClusterNodeT data structure if local interface + not defined in /etc/clusterips, or empty/no /etc/clusterips file present. +* Fixed some basic error reporting in aisexec to use syslog's LOG_ERR instead + of LOG_NOTICE. +* Fixed SEGV if component not found for componentcapabilitymodelget API. + +0.20 +* Correctly parse model values in configuration file for both service + groups and components. +* Changed variables with text nodeexec to aisexec. +* Fixed a bug select wouldn't retry because errno checked for -EINTR + when it should be checking for EINTR. +* Correctly determine startup HA state and send appropriate ha state + changes to registered receivers. + +0.19 +* Implemented saAmfCSISetCallback. +* Implemented saAmfCSIRemoveCallback. +* Implemented saAmfProtectionGroupTrackStart. +* Implemented saAmfProtectionGroupTrackCallback. +* Implemented saAmfProtectionGroupTrackStop. +* Implemented saAmfErrorReport. +* Implemented saAmfErrorCancelAll. +* Implemented saAmfResponse. +* Implemented saAmfComponentCapabilityModelGet. +* Implemented saAmfPendingOperationGet dummy function. + This function will have to be rewritten to be + correct, but completes the API for now. +* Fixed problem where queued messages would not cause select + to be triggered. Occured in component register, unregister, + track start, track stop functions. + +0.18 +* Implemented saAmfReadinessStateSetCallback. +* Implemented saAmfStoppingComplete. +* Implemented saAmfComponentTerminateCallback. +* Implemented saAmfHAStateGet. + +0.17 +* Implemented saAmfHealthcheckCallback. +* Implemented saAmfResponse. +* Implemented saAmfReadinessStateGet. +* Made connect non-blocking to fix bug where blocking connects + could cause timeout on heartbeating. +* Made recv's non-blocking by adding small buffer to each connection + and recving and processing as needed. +* Integrated message dispatch for libais and nodeexec connections. +* Fixed bug where SA_TRACK_CURRENT does not return current state of + cluster membership after second invocation of the testclm application. +* Seperated several functions from main. +* Fixed bug where outqs were not flushed when data present within them + at end of processing loop before next select. Previously they would + only flush when new data was sent on the queues. +* Fixed bug where CLM and AMF always processed dispatch functions in + SA_DISPATCH_BLOCKING mode. + +0.16 +* zero out component data structure during parse. +* make component register/unregister update state in the group list. +* return ERR_NOT_EXIST and ERR_EXIST and BAD_OPERATION error codes for + register and unregister as per spec. +* renamed executive message handlers to include exec in name of handler + function. +* Handle null proxyCompName to register and unregister as per spec. +* Fixed off-by-one in handle database that resulted in badness when + allocating memory after creating any handle (ie: create two handles). +* Added component enumerator which enumerates all components and executes + a function on the component. +* Added component enumerator to unregister all library and nodeexec + connections that are disconnected. + +0.15 +* Added correct time stamping for SaClmClusterNodeT structure. +* Made nodeexec message handlers use the message_handler structure. +* Made nodeexec_process_receive handle messages made of only headers + with no payloads. Previously, nodeexec would lock. +* Seperated heartbeat into two shorter messages one request and one response. +* Changed names of some structures to be more consistent. + +0.14 +* Added simple linked list implementation list.h. +* Modified parser to read data into linked lists. This makes processing + register/unregister/healthchecks/management of HAState easier. +* Exported queue implementation from nodeexec.c to queue.h. +* Seperated parser and parser testing code to seperate source files. +* Modified makefile to build parser test code. +* Modified parser test code to display new linked-list implementation. +* Partially implemented register/unregister/get component name commands + in AMF spec. + +0.13 +* Genericized nodeexec handler so it could run any type of service + and each service has its own set of handler functions as not to crash + the node executive. This allows a set of messages to be designed + to not be crashable, vs trying to figure out all of the interactions + between a flat message name space. +* Added size field for messages stored into the outq so + two send_messages in the nodeexec wouldn't crash. The send_message + function requires the size on messages, and the size was retrieved from + the message header. In a two-part send, there is no message header in + the second message. This was resulting in junk data and possible + crashes on messages that must be queued waiting for the libais to + recv on the other end. + This also fixes the MESSAGE_MAGIC value being displayed in some + NodeId fields of the testclm application. +* Changed lots of type names to something more consistent. +* Changed lots of enumerated types names to something more consistent. + +0.12 +* Abstracted some of the networking functions for EINTR and other errors + Added library handle verification and generic handle database mechanism + available for all services. +* Implemented database mechanism and all abstracted functions on cluster + membership service. + +0.11 +* Defined AMF configuration file. +* Added configuration parser for AMF service. +* Defined inital AMF header/c files. + +0.1 +* Initial release of cluster membership service. diff --git a/LICENSE b/LICENSE index e69de29b..7b04a2f8 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,29 @@ +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. diff --git a/Makefile b/Makefile index e69de29b..1cdb1f2f 100644 --- a/Makefile +++ b/Makefile @@ -0,0 +1,51 @@ +# 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. + +# Production mode flags +CFLAGS = -O3 -Wall +LDFLAGS = + +# Debug mode flags +#CFLAGS = -g -DDEBUG +#LDFLAGS = -g + +# Profile mode flags +#CFLAGS = -O3 -pg -DDEBUG +#LDFLAGS = -pg + +all: + (cd lib; echo ==== `pwd` ===; $(MAKE) all CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"); + (cd exec; echo ==== `pwd` ===; $(MAKE) all CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"); + (cd test; echo ==== `pwd` ===; $(MAKE) all CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)"); + +clean: + (cd lib; echo ==== `pwd` ===; $(MAKE) clean); + (cd exec; echo ==== `pwd` ===; $(MAKE) clean); + (cd test; echo ==== `pwd` ===; $(MAKE) clean); diff --git a/Makefile.samples b/Makefile.samples index e69de29b..c5d121b8 100644 --- a/Makefile.samples +++ b/Makefile.samples @@ -0,0 +1,63 @@ +# 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. +CFLAGS = -c -O2 -I/usr/include/ais +LDFLAGS = + +all:clean testclm testamf testamf1 testamf2 testamf3 testamf4 testamf5 testamf6 + +cleanup: + rm -f testclm testamf + +testclm: testclm.o + $(CC) $(LDFLAGS) -o testclm testclm.o -lais + +testamf: testamf.o + $(CC) $(LDFLAGS) -o testamf testamf.o -lais + +testamf1: testamf1.o libais.a + $(CC) $(LDFLAGS) -o testamf1 testamf1.o libais.a + +testamf2: testamf2.o libais.a + $(CC) $(LDFLAGS) -o testamf2 testamf2.o libais.a + +testamf3: testamf3.o libais.a + $(CC) $(LDFLAGS) -o testamf3 testamf3.o libais.a + +testamf4: testamf4.o libais.a + $(CC) $(LDFLAGS) -o testamf4 testamf4.o libais.a + +testamf5: testamf5.o libais.a + $(CC) $(LDFLAGS) -o testamf5 testamf5.o libais.a + +testamf6: testamf6.o libais.a + $(CC) $(LDFLAGS) -o testamf6 testamf6.o libais.a + +clean: + rm -f *.o testclm testamf testamf1 testamf2 testamf3 testamf4 testamf5 testamf6 diff --git a/QUICKSTART b/QUICKSTART index e69de29b..2ab23c13 100644 --- a/QUICKSTART +++ b/QUICKSTART @@ -0,0 +1,107 @@ +Application Interface Specification Quckstart Guide +--------------------------------------------------- +This AIS package is broken into four parts. The exec directory contains +all of the code responsible for serving the APIs. The api directory contains +APIs the user can link to. The test directory contains some simple test +programs which exercise the APIs. The directory conf contains example +configuration files which can be copied directly onto the target system. + +The API implements the Cluster Membership (CLM), Availabilty Management +Framework (AMF) and the Checkpointing (CKPT) APIs. + +Configuring the AIS Executive: +----------------------------- +The AIS Executive will automatically determine cluster membership by +communicating on a specified multicast address and port. + +The directory conf contains the file network.conf + +bindnetaddr:192.168.1.0 +mcastaddr:226.94.1.1 +mcastport:6000 + +bindnetaddr specifies the address which the AIS Executive should bind to. +This address should always end in zero. If the local interface taffic +traffic should routed over is 192.168.5.92, set bindnetaddr to 192.168.1.0. + +mcastaddr is a multicast address. The default should work but you may have +a different network configuration. Avoid 225.X.X.X because this is a "config" +multicast address which every multicast capable host joins on system start. + +mcastport specifies the UDP port number. It is possible to use the same +multicast address on a network with the AIS services configured for multiple +UDP ports. + +The directory conf contains the file groups.conf which specifies the failover +groups, service units, components, and policies to be used by the AMF. The +configuration file matches the testamf1-6 programs in the test directory and +can be copied directly. + +These two files should be placed in the /etc/ais directory. + +Building AIS +------------ +AIS requires GCC, LD, and a Linux 2.4 kernel. AIS has been tested on +Debian Sarge, MontaVista Carrier Grade Edition 3.1, and Redhat 9. + +Compile AIS by running make in the root directory. Make can also be run +in the individual directories. Nothing is installed by make. If install +is desired, the files must be copied manually. + +Setup network +------------- +Some networks do not automatically configure the default route. Ensure +the default route is configured or AIS wont be able to communicate with +other nodes. + +[sdake@slickdeal checkpointd]$ /sbin/route +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +10.0.0.6 * 255.255.255.255 UH 0 0 0 tun0 +127.0.0.0 * 255.0.0.0 U 0 0 0 lo +default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0 + +the word default above specifies the default route. If the default route +is missing, specify one by + +unix# /sbin/route add default gw 192.168.1.1 + +where 192.168.1.1 is the gateway. It is possible to specify an invalid +route which will also make AIS work properly. + +Run AIS Executive +----------------- +Get 2 or more nodes and run the AIS executive on each node. A list of +node IPs should be displayed on stdout when the nodes join a configuration. +Run the aisexec program (after the default route is setup and the config +files are in place). + +Try out the CLM functionality +----------------------------- +Run test/testclm on one node. Then kill and add nodes. This will cause +callbacks to be called in the testclm application which will print out +the node state changes. + +Try out the AIS AMF functionality +--------------------------------- +After aisexec is running + +Run testamf1 on one node, testamf3 testamf4 on another node. +One will become active one standby. testamf2 is special in that it shows +reporting and canceling an error. Run testamf2 on the node testamf1 +was run from. The ha states and readiness states will be shown. + +Try out the AIS CKPT functionality +---------------------------------- +run ckptstress. This will write checkpoint data as quickly as possible to +the cluster. + +Write your own applications +--------------------------- +Without real applications, finding the hard bugs will be difficult. Please +port or write apps and let us know of the progress! + +Contribute! +----------- +Code, examples, documentation, bug reports, testing are all appreciated. +Read the TODO or the ask on the mailing lists for ways to contribute. diff --git a/README.devmap b/README.devmap index e69de29b..8db638b1 100644 --- a/README.devmap +++ b/README.devmap @@ -0,0 +1,169 @@ +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. + +------------------------------------------------------------------------------- +Files, purpose, and dependencies. +------------------------------------------------------------------------------- + +*----------------* +*- AIS INCLUDES -* +*----------------* + +include/ais_amf.h +----------------- + Definitions for AMF interface. + +include/ais_ckpt.h +------------------ + Definitions for CKPT interface. + +include/ais_clm.h +----------------- + Definitions for CLM interface. + +include/ais_msg.h +----------------- + All the stuff that is used to specify how lib and executive communicate + including message identifiers, message request data, and mesage response + data. + +include/ais_types.h +------------------- + Base type definitions for AIS interface. + +include/list.h +------------- + Doubly linked list inline implementation. + +include/queue.h +--------------- + FIFO queue inline implementation. + + depends on list. + +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/ckpt.c +---------- + CKPT user library linked into user application. + +lib/clm.c +--------- + CLM user library linked into user application. + +lib/util.c +---------- + Utility functions used by all libraries. + +*-----------------* +*- AIS EXECUTIVE -* +*-----------------* + +exec/amf.{h|c} +------------- + Server side implementation of Availability Management Framework (AMF API). + +exec/ckpt.{h|c} + Server side implementation of Checkpointing (CKPT API). + +exec/clm.{h|c} + Server side implementation of Cluster Membership (CLM API). + + +exec/gmi.{h|c} +-------------- + group messaging interface supporting reliable totally ordered group multicast + using ring topology. Supports extended virtual synchrony delivery semantics + with strong membership guarantees. + + depends on cglpoll. + depends on queue. + depends on sq. + depends on list. + +exec/handlers.h +--------------- + Functional specification of a service that connects into AIS executive. + If all functions are implemented, new services can easily be added. + +exec/main.{h|c} +-------------- + Main dispatch functionality and global data types used to connect AIS + services into one component. + +exec/mempool.{h|c} +------------------ + Memory pool implementation that supports preallocated memory blocks to + avoid OOM errors. + +exec/parse.{h|c} +---------------- + Parsing functions for parsing /etc/ais/groups.conf and + /etc/ais/network.conf into internally used data structures. + +exec/poll.{h|c} +--------------- + poll abstraction with support for nearly unlimited large poll handlers + and timer handlers. + + depends on tlist. + +exec/print.{h|c} +---------------- + Logging implementation meant to replace syslog. syslog has nasty side + effect of causing a signal every time a message is logged. + +exec/tlist.{h|c} +----------------- + Timer list interface for supporting timer addition, removal, expiry, and + determination of timeout period left for next timer to expire. + + depends on list. + +exec/log/print.{h|c} +-------------------- + Prototype implementation of logging to syslog without using syslog C + library call. + +loc +--- +Counts the lines of code in the AIS implementation. diff --git a/TODO b/TODO index e69de29b..83957c32 100644 --- a/TODO +++ b/TODO @@ -0,0 +1,67 @@ +Application Interface Specification TODO list + +Generic Items +------------- +* EVT, DLOCK, MSG APIs functionality need to be developed. +* Error checking on parameters could use improvement. +* Allow AIS Executive to configure cluster name. +* Compliance testing of return values would be helpful. +* Support B.01.01 version of spec (currently support A.01.01 version). +* Consider implementing SOCK_SEQPACKET for the AF_UNIX family of sockets on + Linux. This would save an extra system call every time an operation must + be done from the API. +* There are lots of TODO's in the code that need attention. + +Group Messaging Interface +------------------------- +* Very important: single node may not work too well. Debug this + mode of operation. +* Very important: implement full EVS semantics when holes occur in + delivery messages after a configuration change but before the new + configuration is delivered. +* Very important: block new messages from being multicast until recovery + of each service has completed after a configuration change. This could be + done with a "plug" in the token which "stops" any GMI_PRIO_MED or GMI_PRIO_LOW + messages from being multicast until all members of the configuration have + unplugged the token. Then queued messages in MED or LOW priority can be + sent, ensuring correct partition operation. +* Implement error creation config file to test GMI since all my lossy + hardware has been fixed. +* Add secrecy/authentication to group messaging interface. +* Add support for multiple rings with gateway ring to ring for added scalability + in LANs. +* Add support for multiple rings with gateway tuned to long haul networks for + added scalability in WANs. Look at spread.org as a design. +* Add support for low delivery-time delay FIFO messages. +* Add support for SAFE ordering. +* Add support for encryption/authentication using Helix. nonce will start + at zero and increment for every message sent or rotation on the ring. Group + key produced using group key generation protocol. + +Cluster Membership +------------------ +* Make timeout on SaClmClusterNodeGet work. Currently the timeout is 5 + seconds, but the spec requires the timeout to be specified in the API call. + +Availability Management Framework +--------------------------------- +* Very Important: Implement configuration change support. This includes partitions. +* Currently the executive can record and manage only one component service + instance per component. As a result, one component cannot act as standby/active + for two other components in the system (AIS Spec page 74 Figure 16. Example of + n+1 redundancy model). + - Fix to follow spec. +* If a user of the AMF library doesn't respond with saAmfResponse, the state + of the application will never change. Fix by adding timeouts to readiness state + and ha state changes to force saAmfResponse state changes triggered. +* Create array namespace for each invocation id per connection to avoid + cross file descriptor contamination. +* Implement resource proxy functions. (currently dummy functions) +* Implement pending operations. (currently dummy functions) +* Implement NWAY and NWAYACTIVE redundancy models. + +Checkpointing +------------- +* Very Important: Implement configuration change support. This includes partitions. +* Implement thread support for checkpointing library. +* Implement expiration times on checkpoints. diff --git a/conf/groups.conf b/conf/groups.conf index e69de29b..ca52614a 100644 --- a/conf/groups.conf +++ b/conf/groups.conf @@ -0,0 +1,58 @@ +# Test configuration file + +group { + name=raid + model=nplusm + active-units=1 + backup-units=2 + + unit { + name=raidA + component { + name=comp_a_in_su_x + model=x_active + } + component { + name=comp_b_in_su_x + model = x_active + } + } + unit { + name=raidB + component { + name=comp_a_in_su_y + model=x_active + } + component { + name=comp_b_in_su_y + model = x_active + } + } + unit { + name=raidC + component { + name=comp_a_in_su_z + model=x_active + } + component { + name=comp_b_in_su_z + model = x_active + } + } +# protection group has the same name as a component service instance +# if one entity of a component service instance fails, the entire +# service unit fails over to another service unit in the service +# instance + protection { + name = pgA + member = comp_a_in_su_x + member = comp_a_in_su_y + member = comp_a_in_su_z + } + protection { + name = pgB + member = comp_b_in_su_x + member = comp_b_in_su_y + member = comp_b_in_su_z + } +} diff --git a/conf/network.conf b/conf/network.conf index e69de29b..e8c57025 100644 --- a/conf/network.conf +++ b/conf/network.conf @@ -0,0 +1,3 @@ +bindnetaddr:192.168.1.0 +mcastaddr:226.94.1.1 +mcastport:6000 diff --git a/exec/Makefile b/exec/Makefile index e69de29b..a8fa0f3a 100644 --- a/exec/Makefile +++ b/exec/Makefile @@ -0,0 +1,55 @@ +# 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. + +# Production mode flags +#CFLAGS = -O3 -Wall +#LDFLAGS = + +# Debug mode flags +CFLAGS = -g -Wall +# -DDEBUG +LDFLAGS = -g + +# Profile mode flags +#CFLAGS = -O3 -pg +#LDFLAGS = -pg + +OBJS = main.o parse.o tlist.o mempool.o poll.o gmi.o clm.o amf.o ckpt.o print.o + +all:aisexec + +aisexec: $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o aisexec + +clean: + rm -f *.o aisexec gmon.out + +%.o: %.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< diff --git a/exec/amf.c b/exec/amf.c index e69de29b..e59b1630 100644 --- a/exec/amf.c +++ b/exec/amf.c @@ -0,0 +1,2176 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_msg.h" +#include "../include/list.h" +#include "../include/queue.h" +#include "gmi.h" +#include "poll.h" +#include "mempool.h" +#include "parse.h" +#include "main.h" +#include "print.h" +#include "handlers.h" + +#ifdef INPARSEDOTH +enum amfOperationalState { + AMF_OPER_DISABLED, + AMF_OPER_ENABLED +}; + +enum amfAdministrativeState { + AMF_ADMIN_UNLOCKED, + AMF_ADMIN_LOCKED, + AMF_ADMIN_STOPPING +}; + +enum amfOperationalAdministrativeState { + AMF_ENABLED_UNLOCKED, + AMF_DISABLED_UNLOCKED, + AMF_DISABLED_LOCKED, + AMF_ENABLED_STOPPING +}; + + +/* + * State machines for states in AMF + */ +enum amfEnabledUnlockedState { + AMF_ENABLED_UNLOCKED_INITIAL, + AMF_ENABLED_UNLOCKED_IN_SERVICE_REQUESTED, + AMF_ENABLED_UNLOCKED_IN_SERVICE_COMPLETED, + AMF_ENABLED_UNLOCKED_ACTIVE_REQUESTED, + AMF_ENABLED_UNLOCKED_ACTIVE_COMPLETED, + AMF_ENABLED_UNLOCKED_STANDBY_REQUESTED, + AMF_ENABLED_UNLOCKED_STANDBY_COMPLETED, +}; + +enum amfDisabledUnlockedState { + AMF_DISABLED_UNLOCKED_INITIAL, + AMF_DISABLED_UNLOCKED_QUIESCED_REQUESTED, + AMF_DISABLED_UNLOCKED_QUIESCED_COMPLETED, + AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_REQUESTED, + AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_COMPLETED +}; + +enum amfDisabledLockedState { + AMF_DISABLED_LOCKED_INITIAL, + AMF_DISABLED_LOCKED_QUIESCED_REQUESTED, + AMF_DISABLED_LOCKED_QUIESCED_COMPLETED, + AMF_DISABLED_LOCKED_OUT_OF_SERVICE_REQUESTED + AMF_DISABLED_LOCKED_OUT_OF_SERVICE_COMPLETED, +}; + +enum amfEnabledStoppingState { + AMF_ENABLED_STOPPING_INITIAL, + AMF_ENABLED_STOPPING_STOPPING_REQUESTED, + AMF_ENABLED_STOPPING_STOPPING_COMPLETED, +}; + +/* + * Internal Functions + */ +static void componentOutOfServiceSetNoApi ( + struct saAmfComponent *component); + +#endif +static void grow_amf_track_table ( + int fd, + int growby); + +static void sendProtectionGroupNotification ( + int fd, + SaAmfProtectionGroupNotificationT *notificationBufferAddress, + struct saAmfProtectionGroup *amfProtectionGroup, + struct saAmfComponent *changedComponent, + SaAmfProtectionGroupChangesT changeToComponent, + SaUint8T trackFlags); + +static int activeServiceUnitsCount ( + struct saAmfGroup *saAmfGroup); + +#ifdef COMPILE_OUT +static void enumerateComponents ( + void (*function)(struct saAmfComponent *, void *data), + void *data); + + +static void CSIRemove ( + int fd); + +static void haStateSetClusterInit ( + int fd, + struct saAmfComponent *saAmfComponent); +#endif + +static void haStateSetCluster ( + struct saAmfComponent *saAmfComponent, + SaAmfHAStateT haState); + +static void readinessStateSetApi ( + struct saAmfComponent *component, + SaAmfReadinessStateT readinessState); + +#ifdef COMPILE_OUT +static void readinessStateSetClusterInit ( + int fd, + struct saAmfComponent *saAmfComponent); +#endif + +static void readinessStateSetCluster ( + struct saAmfComponent *saAmfComponent, + SaAmfReadinessStateT readinessState); + +#ifdef COMPILE_OUT +static void enumerateComponentsClusterInit ( + struct saAmfComponent *component, + void *data); +#endif + +static void dsm ( + struct saAmfComponent *saAmfComponent); + +#if 0 /* NOT IMPLEMENTED */ +static void componentTerminate ( + int fd); +#endif + +static void timer_function_libamf_healthcheck ( + void *data); + +static struct saAmfProtectionGroup *findProtectionGroup ( + SaNameT *csiName); + +static struct saAmfComponent *findComponentInProtectionGroup ( + SaNameT *csiName, + SaNameT *compName); + +static void sendProtectionGroupNotifications ( + struct saAmfComponent *changedComponent, + SaAmfProtectionGroupChangesT changeToComponent); + +static void sendProtectionGroupNotification ( + int fd, + SaAmfProtectionGroupNotificationT *notificationBufferAddress, + struct saAmfProtectionGroup *amfProtectionGroup, + struct saAmfComponent *changedComponent, + SaAmfProtectionGroupChangesT changeToComponent, + SaUint8T trackFlags); + +static void response_handler_readinessstatesetcallback ( + int connection, + struct req_amf_response *req_amf_response); + +static void response_handler_csisetcallback ( + int connection, + struct req_amf_response *req_amf_response); + + +static int amfApiFinalize (int fd); + +static int amfExecutiveInitialize (void); + +static int message_handler_req_exec_amf_componentregister (int fd, void *message); + +static int message_handler_req_exec_amf_componentunregister (int fd, void *message); + +static int message_handler_req_exec_amf_errorreport (int fd, void *message); + +static int message_handler_req_exec_amf_errorcancelall (int fd, void *message); + +static int message_handler_req_exec_amf_readinessstateset (int fd, void *message); + +static int message_handler_req_exec_amf_hastateset (int fd, void *message); + +static int message_handler_req_amf_init (int fd, void *message); + +static int message_handler_req_amf_activatepoll (int fd, void *message); + +static int message_handler_req_amf_componentregister (int fd, void *message); + +static int message_handler_req_amf_componentunregister (int fd, void *message); + +static int message_handler_req_amf_readinessstateget (int fd, void *message); + +static int message_handler_req_amf_hastateget (int fd, void *message); + +static int message_handler_req_amf_protectiongrouptrackstart (int fd, void *message); + +static int message_handler_req_amf_protectiongrouptrackstop (int fd, void *message); + +static int message_handler_req_amf_errorreport (int fd, void *message); + +static int message_handler_req_amf_errorcancelall (int fd, void *message); + +static int message_handler_req_amf_stoppingcomplete (int fd, void *message); + +static int message_handler_req_amf_response (int fd, void *message); + +static int message_handler_req_amf_componentcapabilitymodelget (int fd, void *message); + +int (*amf_libais_handler_fns[]) (int fd, void *) = { + message_handler_req_amf_activatepoll, + message_handler_req_amf_componentregister, + message_handler_req_amf_componentunregister, + message_handler_req_amf_readinessstateget, + message_handler_req_amf_hastateget, + message_handler_req_amf_protectiongrouptrackstart, + message_handler_req_amf_protectiongrouptrackstop, + message_handler_req_amf_errorreport, + message_handler_req_amf_errorcancelall, + message_handler_req_amf_stoppingcomplete, + message_handler_req_amf_response, + message_handler_req_amf_componentcapabilitymodelget +}; + +int (*amf_aisexec_handler_fns[]) (int fd, void *) = { + message_handler_req_exec_amf_componentregister, + message_handler_req_exec_amf_componentunregister, + message_handler_req_exec_amf_errorreport, + message_handler_req_exec_amf_errorcancelall, + message_handler_req_exec_amf_readinessstateset, + message_handler_req_exec_amf_hastateset, +}; + +/* + * Exports the interface for the service + */ +struct service_handler amf_service_handler = { + libais_handler_fns: amf_libais_handler_fns, + libais_handler_fns_count: sizeof (amf_libais_handler_fns) / sizeof (int (*)), + aisexec_handler_fns: amf_aisexec_handler_fns, + aisexec_handler_fns_count: sizeof (amf_aisexec_handler_fns) / sizeof (int (*)), + confchg_fn: 0, + libais_init_fn: message_handler_req_amf_init, + libais_exit_fn: amfApiFinalize, + aisexec_init_fn: amfExecutiveInitialize +}; + +static void grow_amf_track_table (int fd, int growby) +{ + struct libamf_ci_trackentry *tracks; + int newsize; + int currsize = connections[fd].ais_ci.u.libamf_ci.trackEntries; + + + newsize = growby + currsize; + + if (newsize > currsize) { + tracks = (struct libamf_ci_trackentry *)mempool_realloc (connections[fd].ais_ci.u.libamf_ci.tracks, + (newsize) * sizeof (struct libamf_ci_trackentry)); + if (tracks == 0) { +#ifdef DEBUG + printf ("grow_amf_track_table: out of memory, woops\n"); +#endif +// TODO + exit (1); + } + memset (&tracks[currsize], 0, growby * sizeof (struct libamf_ci_trackentry)); + connections[fd].ais_ci.u.libamf_ci.trackEntries = newsize; + connections[fd].ais_ci.u.libamf_ci.tracks = tracks; + } +} + +void componentUnregister ( + struct saAmfComponent *component) +{ + struct req_exec_amf_componentunregister req_exec_amf_componentunregister; + struct iovec iovecs[2]; + + /* + * This only works on local components + */ + if (component == 0 || component->local != 1) { + return; + } + log_printf (LOG_LEVEL_DEBUG, "componentUnregister: unregistering component %s\n", + getSaNameT (&component->name)); + component->probableCause = SA_AMF_NOT_RESPONDING; + + req_exec_amf_componentunregister.header.magic = MESSAGE_MAGIC; + req_exec_amf_componentunregister.header.size = sizeof (struct req_exec_amf_componentunregister); + req_exec_amf_componentunregister.header.id = MESSAGE_REQ_EXEC_AMF_COMPONENTUNREGISTER; + + req_exec_amf_componentunregister.source.fd = 0; + req_exec_amf_componentunregister.source.in_addr.s_addr = 0; + + memset (&req_exec_amf_componentunregister.req_lib_amf_componentunregister, + 0, sizeof (struct req_lib_amf_componentunregister)); + memcpy (&req_exec_amf_componentunregister.req_lib_amf_componentunregister.compName, + &component->name, + sizeof (SaNameT)); + + iovecs[0].iov_base = &req_exec_amf_componentunregister; + iovecs[0].iov_len = sizeof (req_exec_amf_componentunregister); + + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); +} + +#ifdef COMPILE_OUT +This should be used for a partition I think +// This should be used for partition changes +void enumerateComponents ( + void (*function)(struct saAmfComponent *, void *data), + void *data) +{ + struct list_head *AmfGroupList; + struct list_head *AmfUnitList; + struct list_head *AmfComponentList; + + struct saAmfGroup *saAmfGroup; + struct saAmfUnit *AmfUnit; + struct saAmfComponent *AmfComponent; + + + /* + * Search all groups + */ + for (AmfGroupList = saAmfGroupHead.next; + AmfGroupList != &saAmfGroupHead; + AmfGroupList = AmfGroupList->next) { + + saAmfGroup = list_entry (AmfGroupList, + struct saAmfGroup, saAmfGroupList); + + /* + * Search all units + */ + for (AmfUnitList = saAmfGroup->saAmfUnitHead.next; + AmfUnitList != &saAmfGroup->saAmfUnitHead; + AmfUnitList = AmfUnitList->next) { + + AmfUnit = list_entry (AmfUnitList, + struct saAmfUnit, saAmfUnitList); + + /* + * Search all components + */ + for (AmfComponentList = AmfUnit->saAmfComponentHead.next; + AmfComponentList != &AmfUnit->saAmfComponentHead; + AmfComponentList = AmfComponentList->next) { + + AmfComponent = list_entry (AmfComponentList, + struct saAmfComponent, saAmfComponentList); + + function (AmfComponent, data); + } + } + } +} +#endif + +int activeServiceUnitsCount (struct saAmfGroup *saAmfGroup) { + struct saAmfUnit *saAmfUnit; + struct saAmfComponent *saAmfComponent; + struct list_head *saAmfComponentList; + struct list_head *saAmfUnitList; + int activeServiceUnits = 0; + int thisServiceUnitActive; + + /* + * Search all units + */ + for (activeServiceUnits = 0, saAmfUnitList = saAmfGroup->saAmfUnitHead.next; + saAmfUnitList != &saAmfGroup->saAmfUnitHead; + saAmfUnitList = saAmfUnitList->next) { + + saAmfUnit = list_entry (saAmfUnitList, + struct saAmfUnit, saAmfUnitList); + + /* + * Search all components + */ + for (thisServiceUnitActive = 1, saAmfComponentList = saAmfUnit->saAmfComponentHead.next; + saAmfComponentList != &saAmfUnit->saAmfComponentHead; + saAmfComponentList = saAmfComponentList->next) { + + saAmfComponent = list_entry (saAmfComponentList, + struct saAmfComponent, saAmfComponentList); + + if (saAmfComponent->currentHAState != SA_AMF_ACTIVE) { + thisServiceUnitActive = 0; + } + } + /* + * If all components are active in service unit, count service unit as active + */ + if (thisServiceUnitActive) { + activeServiceUnits += 1; + } + } + + return (activeServiceUnits); +} + +#ifdef CONFIG_TODO +This should be sent after a service unit is made out of service + +void CSIRemove (int fd) +{ + struct res_amf_csiremovecallback res_amf_csiremovecallback; + + if (connections[fd].active == 0 || + connections[fd].service != SOCKET_SERVICE_AMF) { + + return; + } + + log_printf (LOG_NOTICE_DEBUG, "executing CSI remove callback into API\n"); + + res_amf_csiremovecallback.header.magic = MESSAGE_MAGIC; + res_amf_csiremovecallback.header.id = MESSAGE_RES_AMF_CSIREMOVECALLBACK; + res_amf_csiremovecallback.header.size = sizeof (struct res_amf_csiremovecallback); + res_amf_csiremovecallback.invocation = + req_amf_response_set ( + MESSAGE_REQ_AMF_RESPONSE_SAAMFCSIREMOVECALLBACK, + fd); + + memcpy (&res_amf_csiremovecallback.compName, + &connections[fd].component->name, sizeof (SaNameT)); + memcpy (&res_amf_csiremovecallback.csiName, + &connections[fd].component->saAmfProtectionGroup->name, sizeof (SaNameT)); + + res_amf_csiremovecallback.csiFlags = SA_AMF_CSI_ALL_INSTANCES; + libais_send_response (fd, &res_amf_csiremovecallback, + sizeof (struct res_amf_csiremovecallback)); +} +#endif + +void haStateSetApi (struct saAmfComponent *component, SaAmfHAStateT haState) +{ + struct res_amf_csisetcallback res_amf_csisetcallback; + + log_printf (LOG_LEVEL_DEBUG, "sending ha state to API\n"); + + if (component->local != 1) { + return; + } + if (component->probableCause == SA_AMF_NOT_RESPONDING) { + return; + } + /* + * this should be an assertion + */ + if (connections[component->fd].active == 0 || + connections[component->fd].service != SOCKET_SERVICE_AMF) { + return; + } + + res_amf_csisetcallback.header.magic = MESSAGE_MAGIC; + res_amf_csisetcallback.header.id = MESSAGE_RES_AMF_CSISETCALLBACK; + res_amf_csisetcallback.header.size = sizeof (struct res_amf_csisetcallback); + res_amf_csisetcallback.invocation = + req_amf_response_set ( + MESSAGE_REQ_AMF_RESPONSE_SAAMFCSISETCALLBACK, + component->fd); + memcpy (&res_amf_csisetcallback.compName, + &component->name, sizeof (SaNameT)); + memcpy (&res_amf_csisetcallback.csiName, + &component->saAmfProtectionGroup->name, sizeof (SaNameT)); + res_amf_csisetcallback.csiFlags = SA_AMF_CSI_ALL_INSTANCES; + res_amf_csisetcallback.haState = haState; + // TODO set activeCompName to correct component name + memcpy (&res_amf_csisetcallback.activeCompName, + &component->name, sizeof (SaNameT)); + res_amf_csisetcallback.transitionDescriptor = SA_AMF_CSI_NEW_ASSIGN; + + component->newHAState = haState; + + libais_send_response (component->fd, &res_amf_csisetcallback, + sizeof (struct res_amf_csisetcallback)); +} + +#ifdef COMPILE_OUT + +void haStateSetClusterInit ( + int fd, + struct saAmfComponent *saAmfComponent) +{ + struct req_exec_amf_hastatesetcluster req_exec_amf_hastatesetcluster; + + return; + req_exec_amf_hastatesetcluster.header.magic = MESSAGE_MAGIC; + req_exec_amf_hastatesetcluster.header.id = MESSAGE_REQ_EXEC_AMF_HASTATESET; + req_exec_amf_hastatesetcluster.header.size = sizeof (struct req_exec_amf_hastatesetcluster); + memcpy (&req_exec_amf_hastatesetcluster.compName, + &saAmfComponent->name, sizeof (SaNameT)); + req_exec_amf_hastatesetcluster.haState = saAmfComponent->currentHAState; + + log_printf (LOG_LEVEL_DEBUG, "Sending init ha state message to cluster node to set ha state of component %s\n", getSaNameT (&saAmfComponent->name)); + log_printf (LOG_LEVEL_DEBUG, "ha state is %d\n", saAmfComponent->currentHAState); + + libais_send_response (fd, &req_exec_amf_hastatesetcluster, + sizeof (struct req_exec_amf_hastatesetcluster)); +} +#endif + +void haStateSetCluster ( + struct saAmfComponent *component, + SaAmfHAStateT haState) +{ + + struct req_exec_amf_hastateset req_exec_amf_hastateset; + struct iovec iovecs[2]; + + req_exec_amf_hastateset.header.magic = MESSAGE_MAGIC; + req_exec_amf_hastateset.header.id = MESSAGE_REQ_EXEC_AMF_HASTATESET; + req_exec_amf_hastateset.header.size = sizeof (struct req_exec_amf_hastateset); + memcpy (&req_exec_amf_hastateset.compName, &component->name, sizeof (SaNameT)); + req_exec_amf_hastateset.haState = haState; + + log_printf (LOG_LEVEL_DEBUG, "Sending ha state to cluster for component %s\n", getSaNameT (&component->name)); + log_printf (LOG_LEVEL_DEBUG, "ha state is %d\n", haState); + + iovecs[0].iov_base = &req_exec_amf_hastateset; + iovecs[0].iov_len = sizeof (req_exec_amf_hastateset); + + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); +} + +void readinessStateSetApi (struct saAmfComponent *component, + SaAmfReadinessStateT readinessState) +{ + struct res_amf_readinessstatesetcallback res_amf_readinessstatesetcallback; + + /* + * If component is local, don't request service from API + */ + if (component->local != 1) { + return; + } + if (component->probableCause == SA_AMF_NOT_RESPONDING) { + return; + } + + /* + * this should be an assertion + */ + if (connections[component->fd].active == 0 || + connections[component->fd].service != SOCKET_SERVICE_AMF) { + + return; + } + + res_amf_readinessstatesetcallback.header.magic = MESSAGE_MAGIC; + res_amf_readinessstatesetcallback.header.id = MESSAGE_RES_AMF_READINESSSTATESETCALLBACK; + res_amf_readinessstatesetcallback.header.size = sizeof (struct res_amf_readinessstatesetcallback); + res_amf_readinessstatesetcallback.invocation = + req_amf_response_set ( + MESSAGE_REQ_AMF_RESPONSE_SAAMFREADINESSSTATESETCALLBACK, + component->fd); + memcpy (&res_amf_readinessstatesetcallback.compName, + &connections[component->fd].component->name, sizeof (SaNameT)); + res_amf_readinessstatesetcallback.readinessState = readinessState; + connections[component->fd].component->newReadinessState = readinessState; + + log_printf (LOG_LEVEL_DEBUG, "Setting component->fd %d to readiness state %d\n", component->fd, readinessState); + + libais_send_response (component->fd, &res_amf_readinessstatesetcallback, + sizeof (struct res_amf_readinessstatesetcallback)); +} + +#ifdef COMPILE_OUT +void readinessStateSetClusterInit ( + int fd, + struct saAmfComponent *saAmfComponent) +{ + + struct req_exec_amf_readinessstatesetcluster req_exec_amf_readinessstatesetcluster; + + return; + req_exec_amf_readinessstatesetcluster.header.magic = MESSAGE_MAGIC; + req_exec_amf_readinessstatesetcluster.header.id = MESSAGE_REQ_EXEC_AMF_READINESSSTATESET; + req_exec_amf_readinessstatesetcluster.header.size = sizeof (struct req_exec_amf_readinessstateset); + memcpy (&req_exec_amf_readinessstatesetcluster.compName, + &saAmfComponent->name, sizeof (SaNameT)); + req_exec_amf_readinessstatesetcluster.readinessState = saAmfComponent->currentReadinessState; + + log_printf (LOG_LEVEL_DEBUG, "Sending init message to one cluster node to set readiness state of component %s\n", getSaNameT (&saAmfComponent->name)); + log_printf (LOG_LEVEL_DEBUG, "readiness state is %d\n", saAmfComponent->currentReadinessState); + + libais_send_response (fd, &req_exec_amf_readinessstatesetcluster, + sizeof (struct req_exec_amf_readinessstatesetcluster)); +} +#endif + +void readinessStateSetCluster ( + struct saAmfComponent *component, + SaAmfReadinessStateT readinessState) +{ + + struct req_exec_amf_readinessstateset req_exec_amf_readinessstateset; + struct iovec iovecs[2]; + + req_exec_amf_readinessstateset.header.magic = MESSAGE_MAGIC; + req_exec_amf_readinessstateset.header.id = MESSAGE_REQ_EXEC_AMF_READINESSSTATESET; + req_exec_amf_readinessstateset.header.size = sizeof (struct req_exec_amf_readinessstateset); + memcpy (&req_exec_amf_readinessstateset.compName, &component->name, sizeof (SaNameT)); + req_exec_amf_readinessstateset.readinessState = readinessState; + + log_printf (LOG_LEVEL_DEBUG, "Sending message to all cluster nodes to set readiness state of component %s\n", + getSaNameT (&component->name)); + log_printf (LOG_LEVEL_DEBUG, "readiness state is %d\n", readinessState); + + iovecs[0].iov_base = &req_exec_amf_readinessstateset; + iovecs[0].iov_len = sizeof (req_exec_amf_readinessstateset); + + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); +} + +#ifdef CMOPILE_OUT +void enumerateComponentsClusterInit ( + struct saAmfComponent *component, + void *data) +{ + int fd = (int)data; + + return; + readinessStateSetClusterInit (fd, component); + haStateSetClusterInit (fd, component); +} +#endif + +static void dsmDisabledUnlockedRegisteredOrErrorCancel ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + int serviceUnitEnabled; + + log_printf (LOG_LEVEL_DEBUG, "dsmDisabledUnlockedRegisteredOrErrorCancel for %s\n", + getSaNameT (&component->name)); + + unit = component->saAmfUnit; + for (serviceUnitEnabled = 1, list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, + struct saAmfComponent, saAmfComponentList); + + if (component->registered == 0 || + component->probableCause) { + log_printf (LOG_LEVEL_DEBUG, "dsm: Can't transition states, found component not registered or failed.\n", getSaNameT (&component->name)); + serviceUnitEnabled = 0; + break; + } + } + if (serviceUnitEnabled == 1) { + log_printf (LOG_LEVEL_DEBUG, "dsm entering AMF_ENABLED_UNLOCKED state.\n"); + component->saAmfUnit->operationalAdministrativeState = AMF_ENABLED_UNLOCKED; + component->disabledUnlockedState = -1; // SHOULD BE INVALID + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_INITIAL; + dsm (component); + } +} + +static void dsmDisabledUnlockedFailed ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + + unit = component->saAmfUnit; + + for (list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + log_printf (LOG_LEVEL_DEBUG, "dsmDisabledUnlockedFailed: for %s.\n", + getSaNameT (&component->name)); + switch (component->enabledUnlockedState) { + case AMF_ENABLED_UNLOCKED_IN_SERVICE_REQUESTED: + case AMF_ENABLED_UNLOCKED_IN_SERVICE_COMPLETED: + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_REQUESTED; + if (component->probableCause == SA_AMF_NOT_RESPONDING) { + readinessStateSetCluster (component, SA_AMF_OUT_OF_SERVICE); + } else { + readinessStateSetApi (component, SA_AMF_OUT_OF_SERVICE); + } + break; + + case AMF_ENABLED_UNLOCKED_ACTIVE_REQUESTED: + case AMF_ENABLED_UNLOCKED_ACTIVE_COMPLETED: + case AMF_ENABLED_UNLOCKED_STANDBY_REQUESTED: + case AMF_ENABLED_UNLOCKED_STANDBY_COMPLETED: + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_QUIESCED_REQUESTED; + if (component->probableCause == SA_AMF_NOT_RESPONDING) { + haStateSetCluster (component, SA_AMF_QUIESCED); + } else { + haStateSetApi (component, SA_AMF_QUIESCED); + } + poll_timer_delete (aisexec_poll_handle, + component->timer_healthcheck); + component->timer_healthcheck = 0; + break; + + default: + log_printf (LOG_LEVEL_DEBUG, "invalid case 5 %d\n", component->enabledUnlockedState); + break; + } + } +} + +static void dsmDisabledUnlockedQuiescedRequested ( + struct saAmfComponent *component) +{ + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_QUIESCED_COMPLETED; + dsm (component); +} + +static void dsmDisabledUnlockedQuiescedCompleted ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + int serviceUnitQuiesced; + + unit = component->saAmfUnit; + for (serviceUnitQuiesced = 1, list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + if (component->probableCause != SA_AMF_NOT_RESPONDING && component->registered) { + if (component->currentHAState != SA_AMF_QUIESCED) { + log_printf (LOG_LEVEL_DEBUG, "dsm: Can't transition states, found component not quiesced.\n", getSaNameT (&component->name)); + serviceUnitQuiesced = 0; + break; + } + } + } + if (serviceUnitQuiesced == 1) { + log_printf (LOG_LEVEL_DEBUG, "All components have quiesced, Quiescing completed\n"); + for (list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + log_printf (LOG_LEVEL_DEBUG, "dsm: Sending readiness state set to OUTOFSERVICE for comp %s.\n", + getSaNameT (&component->name)); + readinessStateSetApi (component, SA_AMF_OUT_OF_SERVICE); + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_REQUESTED; + } + } +} + +static void dsmDisabledUnlockedOutOfServiceRequested ( + struct saAmfComponent *component) +{ + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_COMPLETED; + dsm (component); +} + +static void dsmDisabledUnlockedOutOfServiceCompleted ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + int serviceUnitOutOfService; + struct saAmfGroup *group = 0; + struct list_head *comp_list = 0; + struct list_head *unit_list = 0; + int serviceUnitInStandby = 0; + + /* + * Once all components of a service unit are out of service, + * activate another service unit in standby + */ + log_printf (LOG_LEVEL_DEBUG, "dsmDisabledUnlockedOutOfServiceCompleted: component out of service %s\n", getSaNameT (&component->name)); + /* + * Determine if all components have responded to going out of service + */ + + unit = component->saAmfUnit; + for (serviceUnitOutOfService = 1, list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + if (component->probableCause != SA_AMF_NOT_RESPONDING && component->registered) { + if (component->currentReadinessState != SA_AMF_OUT_OF_SERVICE) { + log_printf (LOG_LEVEL_DEBUG, "dsm: Can't transition states, found component not quiesced.\n", getSaNameT (&component->name)); + serviceUnitOutOfService = 0; + break; + } + } + } + + group = unit->saAmfGroup; + if (serviceUnitOutOfService == 1) { + log_printf (LOG_LEVEL_DEBUG, "SU has gone out of service.\n"); + /* + * Search all units + */ + for (unit_list = group->saAmfUnitHead.next; + unit_list != &group->saAmfUnitHead; + unit_list = unit_list->next) { + + unit = list_entry (unit_list, + struct saAmfUnit, saAmfUnitList); + + log_printf (LOG_LEVEL_DEBUG, "Checking if service unit is in standby %s\n", getSaNameT (&unit->name)); + /* + * Search all components + */ + for (serviceUnitInStandby = 1, + comp_list = unit->saAmfComponentHead.next; + comp_list != &unit->saAmfComponentHead; + comp_list = comp_list->next) { + + component = list_entry (comp_list, + struct saAmfComponent, saAmfComponentList); + + if (component->currentHAState != SA_AMF_STANDBY) { + serviceUnitInStandby = 0; + break; /* for iteration of service unit components */ + } + } + if (serviceUnitInStandby) { + break; /* for iteration of service group's service units */ + } + } + + /* + * All components in service unit are standby, activate standby service unit + */ + if (serviceUnitInStandby) { + log_printf (LOG_LEVEL_DEBUG, "unit in standby\n"); + for (list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, + struct saAmfComponent, saAmfComponentList); + + haStateSetApi (component, SA_AMF_ACTIVE); + } + } else { + log_printf (LOG_LEVEL_DEBUG, "Can't activate standby service unit because no standby is available.\n"); + } + } +} + +static void dsmEnabledUnlockedInitial ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + + unit = component->saAmfUnit; + for (list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + readinessStateSetApi (component, SA_AMF_IN_SERVICE); + log_printf (LOG_LEVEL_DEBUG, "dsm: telling component %s to enter SA_AMF_IN_SERVICE.\n", + getSaNameT (&component->name)); + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_IN_SERVICE_REQUESTED; + } +} +static void dsmEnabledUnlockedInServiceRequested ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + int in_service; + + log_printf (LOG_LEVEL_DEBUG, "dsmEnabledUnlockedInServiceRequested %s.\n", getSaNameT (&component->name)); + + unit = component->saAmfUnit; + for (in_service = 1, list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + if (component->currentReadinessState != SA_AMF_IN_SERVICE) { + log_printf (LOG_LEVEL_DEBUG, "dsm: Found atleast one component not in service\n"); + in_service = 0; + break; + } + } + if (in_service) { + log_printf (LOG_LEVEL_DEBUG, "DSM determined component is in service\n"); + + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_IN_SERVICE_COMPLETED; + dsm (component); + } +} + +static void dsmEnabledUnlockedInServiceCompleted ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + SaAmfHAStateT newHaState; + int activeServiceUnits; + + log_printf (LOG_LEVEL_DEBUG, "dsmEnabledUnlockedInServiceCompleted %s.\n", getSaNameT (&component->name)); + + unit = component->saAmfUnit; + for (list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, + struct saAmfComponent, saAmfComponentList); + + log_printf (LOG_LEVEL_DEBUG, "Requesting component go active.\n", getSaNameT (&component->name)); + + /* + * Count number of active service units + */ + activeServiceUnits = activeServiceUnitsCount (component->saAmfUnit->saAmfGroup); + if (activeServiceUnits < component->saAmfUnit->saAmfGroup->saAmfActiveUnitsDesired) { + + newHaState = SA_AMF_ACTIVE; + log_printf (LOG_LEVEL_DEBUG, "Setting ha state of component %s to SA_AMF_ACTIVE\n", getSaNameT (&component->name)); + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_ACTIVE_REQUESTED; + } else { + newHaState = SA_AMF_STANDBY; + log_printf (LOG_LEVEL_DEBUG, "Setting ha state of component %s to SA_AMF_STANDBY\n", getSaNameT (&component->name)); + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_STANDBY_REQUESTED; + } + haStateSetApi (component, newHaState); + } +} + +void dsmEnabledUnlockedActiveRequested ( + struct saAmfComponent *component) +{ + if (component->local == 1) { + log_printf (LOG_LEVEL_DEBUG, "Adding healthcheck timer\n"); + poll_timer_add (aisexec_poll_handle, + component->healthcheckInterval, + (void *)component->fd, + timer_function_libamf_healthcheck, + &component->timer_healthcheck); + } + + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_ACTIVE_COMPLETED; +} + +void dsmEnabledUnlockedStandbyRequested ( + struct saAmfComponent *component) +{ + if (component->local == 1) { + + log_printf (LOG_LEVEL_DEBUG, "Adding healthcheck timer\n"); + + poll_timer_add (aisexec_poll_handle, + component->healthcheckInterval, + (void *)component->fd, + timer_function_libamf_healthcheck, + &component->timer_healthcheck); + } + + component->enabledUnlockedState = AMF_ENABLED_UNLOCKED_STANDBY_COMPLETED; +} + +void dsmEnabledUnlockedTransitionDisabledUnlocked ( + struct saAmfComponent *component) +{ + struct saAmfUnit *unit; + struct list_head *list; + + unit = component->saAmfUnit; + for (list = unit->saAmfComponentHead.next; + list != &unit->saAmfComponentHead; + list = list->next) { + + component = list_entry (list, struct saAmfComponent, saAmfComponentList); + + log_printf (LOG_LEVEL_DEBUG, "Requesting component %s transition to disabled.\n", + getSaNameT (&component->name)); + + component->saAmfUnit->operationalAdministrativeState = AMF_DISABLED_UNLOCKED; + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_FAILED; + } + dsm (component); +} + +static void dsmEnabledUnlocked ( + struct saAmfComponent *component) +{ + switch (component->enabledUnlockedState) { + case AMF_ENABLED_UNLOCKED_INITIAL: + dsmEnabledUnlockedInitial (component); + break; + case AMF_ENABLED_UNLOCKED_IN_SERVICE_REQUESTED: + dsmEnabledUnlockedInServiceRequested (component); + break; + case AMF_ENABLED_UNLOCKED_IN_SERVICE_COMPLETED: + dsmEnabledUnlockedInServiceCompleted (component); + break; + case AMF_ENABLED_UNLOCKED_ACTIVE_REQUESTED: + dsmEnabledUnlockedActiveRequested (component); + break; + case AMF_ENABLED_UNLOCKED_ACTIVE_COMPLETED: + /* noop - operational state */ + break; + case AMF_ENABLED_UNLOCKED_STANDBY_REQUESTED: + dsmEnabledUnlockedActiveRequested (component); + break; + case AMF_ENABLED_UNLOCKED_STANDBY_COMPLETED: + /* noop - operational state */ + break; + + default: + log_printf (LOG_LEVEL_DEBUG, "dsmEnabledUnlocked: unkown state machine value.\n"); + } +} + +static void dsmDisabledUnlocked ( + struct saAmfComponent *component) +{ + log_printf (LOG_LEVEL_DEBUG, "dsmDisabledUnlocked for %s state %d\n", + getSaNameT (&component->name), + component->disabledUnlockedState); + + switch (component->disabledUnlockedState) { + case AMF_DISABLED_UNLOCKED_REGISTEREDORERRORCANCEL: + dsmDisabledUnlockedRegisteredOrErrorCancel (component); + break; + + case AMF_DISABLED_UNLOCKED_FAILED: + dsmDisabledUnlockedFailed (component); + break; + + case AMF_DISABLED_UNLOCKED_QUIESCED_REQUESTED: + dsmDisabledUnlockedQuiescedRequested (component); + break; + + case AMF_DISABLED_UNLOCKED_QUIESCED_COMPLETED: + dsmDisabledUnlockedQuiescedCompleted (component); + break; + + case AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_REQUESTED: + dsmDisabledUnlockedOutOfServiceRequested (component); + break; + + case AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_COMPLETED: + dsmDisabledUnlockedOutOfServiceCompleted (component); + break; + + default: + log_printf (LOG_LEVEL_DEBUG, "dsmDisabledUnlocked: unkown state machine value %d.\n", component->disabledUnlockedState); + } +} + +static void dsm ( + struct saAmfComponent *component) +{ + log_printf (LOG_LEVEL_DEBUG, "dsm for component %s\n", getSaNameT (&component->name)); + + switch (component->saAmfUnit->operationalAdministrativeState) { + case AMF_DISABLED_UNLOCKED: + dsmDisabledUnlocked (component); + break; + case AMF_ENABLED_UNLOCKED: + dsmEnabledUnlocked (component); + break; +/* + AMF_DISABLED_LOCKED, + AMF_ENABLED_STOPPING +*/ + default: + log_printf (LOG_LEVEL_DEBUG, "dsm: unknown state machine value.\n"); + } +} + +#if 0 +/* + * This is currently unused, but executes the componentterminatecallback + * callback in the AMF api. + */ +void componentTerminate (int fd) +{ + struct res_amf_componentterminatecallback res_amf_componentterminatecallback; + + res_amf_componentterminatecallback.header.magic = MESSAGE_MAGIC; + res_amf_componentterminatecallback.header.id = MESSAGE_RES_AMF_COMPONENTTERMINATECALLBACK; + res_amf_componentterminatecallback.header.size = sizeof (struct res_amf_componentterminatecallback); + res_amf_componentterminatecallback.invocation = + req_amf_response_set ( + MESSAGE_REQ_AMF_RESPONSE_SAAMFCOMPONENTTERMINATECALLBACK, + fd); + memcpy (&res_amf_componentterminatecallback.compName, + &connections[fd].component->name, sizeof (SaNameT)); + connections[fd].component->newReadinessState = SA_AMF_OUT_OF_SERVICE; + + log_printf (LOG_LEVEL_DEBUG, "terminating component on fd %d\n", fd); + libais_send_response (fd, &res_amf_componentterminatecallback, + sizeof (struct res_amf_componentterminatecallback)); +} +#endif /* Not currently implemented */ + +void errorReport ( + struct saAmfComponent *component, + SaAmfProbableCauseT probableCause) +{ + struct req_exec_amf_errorreport req_exec_amf_errorreport; + struct iovec iovecs[2]; + + req_exec_amf_errorreport.header.magic = MESSAGE_MAGIC; + req_exec_amf_errorreport.header.size = sizeof (struct req_exec_amf_errorreport); + req_exec_amf_errorreport.header.id = MESSAGE_REQ_EXEC_AMF_ERRORREPORT; + + req_exec_amf_errorreport.source.fd = 0; + req_exec_amf_errorreport.source.in_addr.s_addr = 0; + memcpy (&req_exec_amf_errorreport.req_lib_amf_errorreport.erroneousComponent, + &component->name, + sizeof (SaNameT)); + req_exec_amf_errorreport.req_lib_amf_errorreport.errorDescriptor.probableCause = probableCause; + + iovecs[0].iov_base = &req_exec_amf_errorreport; + iovecs[0].iov_len = sizeof (req_exec_amf_errorreport); + + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); +} + +int healthcheck_instance = 0; +void timer_function_libamf_healthcheck (void *data) { + struct res_amf_healthcheckcallback res_amf_healthcheckcallback; + int connection = (int)data; + + res_amf_healthcheckcallback.header.magic = MESSAGE_MAGIC; + res_amf_healthcheckcallback.header.id = MESSAGE_RES_AMF_HEALTHCHECKCALLBACK; + res_amf_healthcheckcallback.header.size = sizeof (struct res_amf_healthcheckcallback); + + log_printf (LOG_LEVEL_DEBUG, "checking healthcheck on component %s\n", + getSaNameT (&connections[connection].component->name)); + if (connections[connection].component->healthcheck_outstanding == 1) { + + log_printf (LOG_LEVEL_DEBUG, "Healthcheck timed out on component %s\n", + getSaNameT (&connections[connection].component->name)); + + /* + * Report the error to the rest of the cluster using the normal state machine + */ + errorReport (connections[connection].component, SA_AMF_NOT_RESPONDING); + + connections[connection].component->healthcheck_outstanding = 2; + } else + if (connections[connection].component->healthcheck_outstanding == 0) { + connections[connection].component->healthcheck_outstanding = 1; + /* + * Send healthcheck message + */ + res_amf_healthcheckcallback.invocation = + req_amf_response_set ( + MESSAGE_REQ_AMF_RESPONSE_SAAMFHEALTHCHECKCALLBACK, + connection); + memcpy (&res_amf_healthcheckcallback.compName, + &connections[connection].component->name, + sizeof (SaNameT)); + res_amf_healthcheckcallback.checkType = SA_AMF_HEARTBEAT; + + log_printf (LOG_LEVEL_DEBUG, "Sending instance %d\n", healthcheck_instance); + res_amf_healthcheckcallback.instance = healthcheck_instance++; + libais_send_response (connection, + &res_amf_healthcheckcallback, + sizeof (struct res_amf_healthcheckcallback)); + + poll_timer_add (aisexec_poll_handle, + connections[connection].component->healthcheckInterval, + (void *)connection, + timer_function_libamf_healthcheck, + &connections[connection].component->timer_healthcheck); + } +} + +struct saAmfProtectionGroup *findProtectionGroup ( + SaNameT *csiName) +{ + struct list_head *AmfGroupList; + struct list_head *AmfProtectionGroupList; + + struct saAmfGroup *saAmfGroup; + struct saAmfProtectionGroup *AmfProtectionGroup; + + /* + * Search all groups + */ + for (AmfGroupList = saAmfGroupHead.next; + AmfGroupList != &saAmfGroupHead; + AmfGroupList = AmfGroupList->next) { + + saAmfGroup = list_entry (AmfGroupList, + struct saAmfGroup, saAmfGroupList); + + /* + * Search all protection groups + */ + for (AmfProtectionGroupList = saAmfGroup->saAmfProtectionGroupHead.next; + AmfProtectionGroupList != &saAmfGroup->saAmfProtectionGroupHead; + AmfProtectionGroupList = AmfProtectionGroupList->next) { + + AmfProtectionGroup = list_entry (AmfProtectionGroupList, + struct saAmfProtectionGroup, saAmfProtectionGroupList); + + if (SaNameTisNameT (csiName, &AmfProtectionGroup->name)) { + return (AmfProtectionGroup); + } + } + } + return (0); +} + +struct saAmfComponent *findComponentInProtectionGroup ( + SaNameT *csiName, + SaNameT *compName) +{ + + struct list_head *AmfGroupList = 0; + struct list_head *AmfProtectionGroupList = 0; + struct list_head *AmfComponentList = 0; + + struct saAmfGroup *saAmfGroup = 0; + struct saAmfProtectionGroup *AmfProtectionGroup = 0; + struct saAmfComponent *AmfComponent = 0; + int found = 0; + + /* + * Search all groups + */ + for (AmfGroupList = saAmfGroupHead.next; + AmfGroupList != &saAmfGroupHead; + AmfGroupList = AmfGroupList->next) { + + saAmfGroup = list_entry (AmfGroupList, + struct saAmfGroup, saAmfGroupList); + + /* + * Search all protection groups + */ + for (AmfProtectionGroupList = saAmfGroup->saAmfProtectionGroupHead.next; + AmfProtectionGroupList != &saAmfGroup->saAmfProtectionGroupHead; + AmfProtectionGroupList = AmfProtectionGroupList->next) { + + AmfProtectionGroup = list_entry (AmfProtectionGroupList, + struct saAmfProtectionGroup, saAmfProtectionGroupList); + + if (SaNameTisNameT (csiName, &AmfProtectionGroup->name)) { + /* + * Search all components + */ + for (AmfComponentList = AmfProtectionGroup->saAmfMembersHead.next; + AmfComponentList != &AmfProtectionGroup->saAmfMembersHead; + AmfComponentList = AmfComponentList->next) { + + AmfComponent = list_entry (AmfComponentList, + struct saAmfComponent, saAmfProtectionGroupList); + + if (SaNameTisNameT (compName, &AmfComponent->name)) { + found = 1; + } + } + } + } + } + + if (found) { + return (AmfComponent); + } else { + return (0); + } +} + +void sendProtectionGroupNotifications ( + struct saAmfComponent *changedComponent, + SaAmfProtectionGroupChangesT changeToComponent) +{ + int fd; + int i; + + log_printf (LOG_LEVEL_DEBUG, "sendProtectionGroupNotifications: sending PGs to API.\n"); + + for (fd = 0; fd < connection_entries; fd++) { + if (connections[fd].active && + connections[fd].service == SOCKET_SERVICE_AMF) { + + for (i = 0; i < connections[fd].ais_ci.u.libamf_ci.trackEntries; i++) { + if (connections[fd].ais_ci.u.libamf_ci.tracks[i].active) { + + sendProtectionGroupNotification (fd, + connections[fd].ais_ci.u.libamf_ci.tracks[i].notificationBufferAddress, + changedComponent->saAmfProtectionGroup, + changedComponent, + changeToComponent, + connections[fd].ais_ci.u.libamf_ci.tracks[i].trackFlags); + } /* if active */ + } /* for all track entries */ + } /* if connection active and service is AMF */ + } /* for all connection entries */ + +} + +void sendProtectionGroupNotification (int fd, + SaAmfProtectionGroupNotificationT *notificationBufferAddress, + struct saAmfProtectionGroup *amfProtectionGroup, + struct saAmfComponent *changedComponent, + SaAmfProtectionGroupChangesT changeToComponent, + SaUint8T trackFlags) +{ + struct res_amf_protectiongrouptrackcallback res_amf_protectiongrouptrackcallback; + SaAmfProtectionGroupNotificationT *protectionGroupNotification = 0; + int notifyEntries = 0; + struct saAmfComponent *component; + struct list_head *componentList; + + /* + * Step through all components and generate protection group list for csi + */ + + for (componentList = amfProtectionGroup->saAmfMembersHead.next; + componentList != &amfProtectionGroup->saAmfMembersHead; + componentList = componentList->next) { + + component = list_entry (componentList, + struct saAmfComponent, saAmfProtectionGroupList); + + /* + * Generate new track entry for following cases: + * 1. If this component is the changed component and + * SA_TRACK_CHANGES_ONLY is set + * 2. If track flags indicate SA_TRACK_CURRENT or SA_TRACK_CHANGES + */ + if (component == changedComponent || + (trackFlags & (SA_TRACK_CURRENT | SA_TRACK_CHANGES))) { + + protectionGroupNotification = (SaAmfProtectionGroupNotificationT *)mempool_realloc (protectionGroupNotification, + sizeof (SaAmfProtectionGroupNotificationT) * (notifyEntries + 1)); + memcpy (&protectionGroupNotification[notifyEntries].member.compName, + &component->name, sizeof (SaNameT)); + memcpy (&protectionGroupNotification[notifyEntries].member.readinessState, + &component->currentReadinessState, sizeof (SaAmfReadinessStateT)); + memcpy (&protectionGroupNotification[notifyEntries].member.haState, + &component->currentHAState, sizeof (SaAmfHAStateT)); + if (component == changedComponent) { + protectionGroupNotification[notifyEntries].change = changeToComponent; + } else { + protectionGroupNotification[notifyEntries].change = SA_AMF_PROTECTION_GROUP_NO_CHANGE; + } + notifyEntries += 1; + } + } /* for */ + + /* + * Send track callback + */ + if (notifyEntries) { + res_amf_protectiongrouptrackcallback.header.magic = MESSAGE_MAGIC; + res_amf_protectiongrouptrackcallback.header.size = + sizeof (struct res_amf_protectiongrouptrackcallback) + + (notifyEntries * sizeof (SaAmfProtectionGroupNotificationT)); + res_amf_protectiongrouptrackcallback.header.id = MESSAGE_RES_AMF_PROTECTIONGROUPTRACKCALLBACK; + res_amf_protectiongrouptrackcallback.numberOfItems = notifyEntries; + res_amf_protectiongrouptrackcallback.numberOfMembers = notifyEntries; + memcpy (&res_amf_protectiongrouptrackcallback.csiName, + &amfProtectionGroup->name, sizeof (SaNameT)); + + res_amf_protectiongrouptrackcallback.notificationBufferAddress = notificationBufferAddress; + libais_send_response (fd, &res_amf_protectiongrouptrackcallback, + sizeof (struct res_amf_protectiongrouptrackcallback)); + + libais_send_response (fd, protectionGroupNotification, + sizeof (SaAmfProtectionGroupNotificationT) * notifyEntries); + + mempool_free (protectionGroupNotification); + } +} + +/* + * The response handler for readiness state set callback + */ +static void response_handler_readinessstatesetcallback (int connection, + struct req_amf_response *req_amf_response) +{ + + if (req_amf_response->error == SA_OK && connections[connection].component) { + log_printf (LOG_LEVEL_DEBUG, "CALLBACK sending readiness state to %s\n", + getSaNameT (&connections[connection].component->name)); + readinessStateSetCluster (connections[connection].component, + connections[connection].component->newReadinessState); + } +} + +/* + * iterate service unit components + * telling all components not already QUIESCING to enter SA_AMF_QUIESCED state + */ +static void response_handler_csisetcallback (int connection, + struct req_amf_response *req_amf_response) +{ + + if (req_amf_response->error == SA_OK && connections[connection].component) { + haStateSetCluster (connections[connection].component, + connections[connection].component->newHAState); + } +} + +int amfExecutiveInitialize (void) +{ + return (0); +} + +int amfApiFinalize (int fd) +{ + /* + * Unregister all components registered to this file descriptor + */ + if (connections[fd].service == SOCKET_SERVICE_AMF) { + componentUnregister (connections[fd].component); + + if (connections[fd].component && connections[fd].component->timer_healthcheck) { + poll_timer_delete (aisexec_poll_handle, + connections[fd].component->timer_healthcheck); + + connections[fd].component->timer_healthcheck = 0; + } + + if (connections[fd].ais_ci.u.libamf_ci.tracks) { + mempool_free (connections[fd].ais_ci.u.libamf_ci.tracks); + connections[fd].ais_ci.u.libamf_ci.tracks = 0; + } + } + + return (0); +} + + +static int message_handler_req_exec_amf_componentregister (int fd, void *message) +{ + struct req_exec_amf_componentregister *req_exec_amf_componentregister = (struct req_exec_amf_componentregister *)message; + struct res_lib_amf_componentregister res_lib_amf_componentregister; + struct saAmfComponent *component; + struct saAmfComponent *amfProxyComponent; + SaErrorT error; + + log_printf (LOG_LEVEL_DEBUG, "Executive: ComponentRegister for component %s\n", + getSaNameT (&req_exec_amf_componentregister->req_lib_amf_componentregister.compName)); + + /* + * Determine if proxy isn't registered + */ + error = SA_OK; + component = findComponent (&req_exec_amf_componentregister->req_lib_amf_componentregister.compName); + amfProxyComponent = findComponent (&req_exec_amf_componentregister->req_lib_amf_componentregister.proxyCompName); + + /* + * If component not in configuration files, return error + */ + if (component == 0) { + error = SA_ERR_NOT_EXIST; + } + + /* + * If proxy doesn't exist and isn't registered, return error + */ + if ((amfProxyComponent == 0 && + req_exec_amf_componentregister->req_lib_amf_componentregister.proxyCompName.length > 0) || + (amfProxyComponent && amfProxyComponent->registered == 0)) { + + error = SA_ERR_NOT_EXIST; + } + + /* + * If component already registered, return error + */ + if (error == SA_OK) { + if (component->registered) { + error = SA_ERR_EXIST; + } + } + + /* + * Finally register component and setup links for proxy if + * proxy present + */ + if (error == SA_OK) { + component->local = 0; + component->registered = 1; + component->fd = req_exec_amf_componentregister->source.fd; + component->currentReadinessState = SA_AMF_OUT_OF_SERVICE; + component->newReadinessState = SA_AMF_OUT_OF_SERVICE; + component->currentHAState = SA_AMF_QUIESCED; + component->newHAState = SA_AMF_QUIESCED; + component->probableCause = 0; + component->enabledUnlockedState = 0; + component->disabledUnlockedState = 0; + + if (req_exec_amf_componentregister->req_lib_amf_componentregister.proxyCompName.length > 0) { + component->saAmfProxyComponent = amfProxyComponent; + } + } + + /* + * If this node originated the request to the cluster, respond back + * to the AMF library + */ + if (req_exec_amf_componentregister->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + if (error == SA_OK) { + component->local = 1; + connections[req_exec_amf_componentregister->source.fd].component = component; + } + + log_printf (LOG_LEVEL_DEBUG, "sending component register response to fd %d\n", req_exec_amf_componentregister->source.fd); + + res_lib_amf_componentregister.header.magic = MESSAGE_MAGIC; + res_lib_amf_componentregister.header.size = sizeof (struct res_lib_amf_componentregister); + res_lib_amf_componentregister.header.id = MESSAGE_RES_AMF_COMPONENTREGISTER; + res_lib_amf_componentregister.error = error; + + libais_send_response (req_exec_amf_componentregister->source.fd, &res_lib_amf_componentregister, + sizeof (struct res_lib_amf_componentregister)); + } + + + /* + * If no error on registration, determine if we should enter new state + */ + if (error == SA_OK) { + dsm (component); + } + + return (0); +} + +static int message_handler_req_exec_amf_componentunregister (int fd, void *message) +{ + struct req_exec_amf_componentunregister *req_exec_amf_componentunregister = (struct req_exec_amf_componentunregister *)message; + struct res_lib_amf_componentunregister res_lib_amf_componentunregister; + struct saAmfComponent *component; + struct saAmfComponent *amfProxyComponent; + SaErrorT error; + + log_printf (LOG_LEVEL_DEBUG, "Executive: ComponentUnregister for %s\n", + getSaNameT (&req_exec_amf_componentunregister->req_lib_amf_componentunregister.compName)); + + component = findComponent (&req_exec_amf_componentunregister->req_lib_amf_componentunregister.compName); + amfProxyComponent = findComponent (&req_exec_amf_componentunregister->req_lib_amf_componentunregister.proxyCompName); + + /* + * Check for proxy and component not existing in system + */ + error = SA_OK; + if (component == 0) { + error = SA_ERR_NOT_EXIST; + } + if (req_exec_amf_componentunregister->req_lib_amf_componentunregister.proxyCompName.length > 0) { + if (amfProxyComponent) { + if (amfProxyComponent->registered == 0) { + error = SA_ERR_NOT_EXIST; + } + } else { + error = SA_ERR_NOT_EXIST; + } + } + + /* + * If there is a proxycompname, make sure it is the proxy + * of compName + */ + if (error == SA_OK && amfProxyComponent) { + if (component->saAmfProxyComponent != amfProxyComponent) { + error = SA_ERR_BAD_OPERATION; + } + } + + /* + * Finally unregister the component + */ + if (error == SA_OK) { + component->registered = 0; + dsmEnabledUnlockedTransitionDisabledUnlocked (component); + } + + /* + * If this node originated the request to the cluster, respond back + * to the AMF library + */ + if (req_exec_amf_componentunregister->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + log_printf (LOG_LEVEL_DEBUG, "sending component unregister response to fd %d\n", + req_exec_amf_componentunregister->source.fd); + + res_lib_amf_componentunregister.header.magic = MESSAGE_MAGIC; + res_lib_amf_componentunregister.header.size = sizeof (struct res_lib_amf_componentunregister); + res_lib_amf_componentunregister.header.id = MESSAGE_RES_AMF_COMPONENTUNREGISTER; + res_lib_amf_componentunregister.error = error; + + libais_send_response (req_exec_amf_componentunregister->source.fd, + &res_lib_amf_componentunregister, sizeof (struct res_lib_amf_componentunregister)); + } + + return (0); +} + +static int message_handler_req_exec_amf_errorreport (int fd, void *message) +{ + struct req_exec_amf_errorreport *req_exec_amf_errorreport = (struct req_exec_amf_errorreport *)message; + struct res_lib_amf_errorreport res_lib_amf_errorreport; + struct saAmfComponent *component; + SaErrorT error = SA_ERR_BAD_OPERATION; + + log_printf (LOG_LEVEL_DEBUG, "Executive: ErrorReport for %s\n", + getSaNameT (&req_exec_amf_errorreport->req_lib_amf_errorreport.erroneousComponent)); + + component = findComponent (&req_exec_amf_errorreport->req_lib_amf_errorreport.erroneousComponent); + if (component && component->registered) { + component->probableCause = req_exec_amf_errorreport->req_lib_amf_errorreport.errorDescriptor.probableCause; + + /* + * One registered component left, so transition + * SU to failed operational state + */ + dsmEnabledUnlockedTransitionDisabledUnlocked (component); + error = SA_OK; + } + + /* + * If this node originated the request to the cluster, respond back + * to the AMF library + */ + if (req_exec_amf_errorreport->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + log_printf (LOG_LEVEL_DEBUG, "sending error report response to fd %d\n", + req_exec_amf_errorreport->source.fd); + + res_lib_amf_errorreport.header.magic = MESSAGE_MAGIC; + res_lib_amf_errorreport.header.size = sizeof (struct res_lib_amf_errorreport); + res_lib_amf_errorreport.header.id = MESSAGE_RES_AMF_ERRORREPORT; + res_lib_amf_errorreport.error = error; + + libais_send_response (req_exec_amf_errorreport->source.fd, + &res_lib_amf_errorreport, sizeof (struct res_lib_amf_errorreport)); + } + + return (0); +} + +static int message_handler_req_exec_amf_errorcancelall (int fd, void *message) +{ + struct req_exec_amf_errorcancelall *req_exec_amf_errorcancelall = (struct req_exec_amf_errorcancelall *)message; + struct res_lib_amf_errorcancelall res_lib_amf_errorcancelall; + struct saAmfComponent *component; + SaErrorT error = SA_ERR_BAD_OPERATION; + + log_printf (LOG_LEVEL_DEBUG, "Executive: ErrorCancelAll for %s\n", + getSaNameT (&req_exec_amf_errorcancelall->req_lib_amf_errorcancelall.compName)); + + component = findComponent (&req_exec_amf_errorcancelall->req_lib_amf_errorcancelall.compName); + if (component && component->registered) { + /* + * Mark component in service if its a AMF service + * connected to this aisexec + */ + if (component->probableCause) { + component->probableCause = 0; + component->disabledUnlockedState = AMF_DISABLED_UNLOCKED_REGISTEREDORERRORCANCEL; + dsm (component); + } + error = SA_OK; + } + + /* + * If this node originated the request to the cluster, respond back + * to the AMF library + */ + if (req_exec_amf_errorcancelall->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + log_printf (LOG_LEVEL_DEBUG, "sending error report response to fd %d\n", + req_exec_amf_errorcancelall->source.fd); + + res_lib_amf_errorcancelall.header.magic = MESSAGE_MAGIC; + res_lib_amf_errorcancelall.header.size = sizeof (struct res_lib_amf_errorcancelall); + res_lib_amf_errorcancelall.header.id = MESSAGE_RES_AMF_ERRORCANCELALL; + res_lib_amf_errorcancelall.error = error; + + libais_send_response (req_exec_amf_errorcancelall->source.fd, + &res_lib_amf_errorcancelall, sizeof (struct res_lib_amf_errorcancelall)); + } + + return (0); +} + +/* + * If receiving this message from another cluster node, another cluster node + * has selected a readiness state for a component connected to _that_ cluster + * node. That cluster node API has verified the readiness state, so its time to let + * the rest of the cluster nodes know about the readiness state change. + */ +static int message_handler_req_exec_amf_readinessstateset (int fd, void *message) +{ + struct req_exec_amf_readinessstateset *req_exec_amf_readinessstateset = (struct req_exec_amf_readinessstateset *)message; + struct saAmfComponent *component; + + component = findComponent (&req_exec_amf_readinessstateset->compName); + if (component) { + log_printf (LOG_LEVEL_DEBUG, "found component %s, setting current readiness state to %d\n", + getSaNameT (&component->name), + req_exec_amf_readinessstateset->readinessState); + + component->currentReadinessState = req_exec_amf_readinessstateset->readinessState; + dsm (component); + } + + return (0); +} + +/* + * If receiving this message from another cluster node, another cluster node + * has selected a ha state for a component connected to _that_ cluster + * node. That cluster node API has verified the ha state, so its time to let + * the rest of the cluster nodes know about the HA state change. + */ +static int message_handler_req_exec_amf_hastateset (int fd, void *message) +{ + struct req_exec_amf_hastateset *req_exec_amf_hastateset = (struct req_exec_amf_hastateset *)message; + struct saAmfComponent *component; + + component = findComponent (&req_exec_amf_hastateset->compName); + if (component) { + log_printf (LOG_LEVEL_DEBUG, "found component %s, setting current HA state to %d\n", + getSaNameT (&component->name), + req_exec_amf_hastateset->haState); + component->currentHAState = req_exec_amf_hastateset->haState; + dsm (component); + } + + return (0); +} + +static int message_handler_req_amf_init (int fd, void *message) +{ + struct res_lib_init res_lib_init; + SaErrorT error = SA_ERR_SECURITY; + + log_printf (LOG_LEVEL_DEBUG, "Got AMF request to initalize availability management framework service.\n"); + + if (connections[fd].authenticated) { + connections[fd].service = SOCKET_SERVICE_AMF; + error = SA_OK; + } + + res_lib_init.header.magic = MESSAGE_MAGIC; + res_lib_init.header.size = sizeof (struct res_lib_init); + res_lib_init.header.id = MESSAGE_RES_INIT; + res_lib_init.error = error; + + libais_send_response (fd, &res_lib_init, sizeof (res_lib_init)); + + if (connections[fd].authenticated) { + return (0); + } + return (-1); +} + +static int message_handler_req_amf_activatepoll (int fd, void *message) +{ + struct res_amf_activatepoll res_amf_activatepoll; + + res_amf_activatepoll.header.magic = MESSAGE_MAGIC; + res_amf_activatepoll.header.size = sizeof (struct res_amf_activatepoll); + res_amf_activatepoll.header.id = MESSAGE_RES_AMF_ACTIVATEPOLL; + libais_send_response (fd, &res_amf_activatepoll, sizeof (struct res_amf_activatepoll)); + + return (0); +} + +static int message_handler_req_amf_componentregister (int fd, void *message) +{ + struct req_amf_componentregister *req_lib_amf_componentregister = (struct req_amf_componentregister *)message; + struct req_exec_amf_componentregister req_exec_amf_componentregister; + struct iovec iovecs[2]; + int result; + + req_exec_amf_componentregister.header.magic = MESSAGE_MAGIC; + req_exec_amf_componentregister.header.size = sizeof (struct req_exec_amf_componentregister); + req_exec_amf_componentregister.header.id = MESSAGE_REQ_EXEC_AMF_COMPONENTREGISTER; + + req_exec_amf_componentregister.source.fd = fd; + req_exec_amf_componentregister.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + memcpy (&req_exec_amf_componentregister.req_lib_amf_componentregister, + req_lib_amf_componentregister, + sizeof (struct req_lib_amf_componentregister)); + + iovecs[0].iov_base = &req_exec_amf_componentregister; + iovecs[0].iov_len = sizeof (req_exec_amf_componentregister); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_amf_componentunregister (int fd, void *message) +{ + struct req_lib_amf_componentunregister *req_lib_amf_componentunregister = (struct req_lib_amf_componentunregister *)message; + struct req_exec_amf_componentunregister req_exec_amf_componentunregister; + struct iovec iovecs[2]; + int result; + struct saAmfComponent *component; + + req_exec_amf_componentunregister.header.magic = MESSAGE_MAGIC; + req_exec_amf_componentunregister.header.size = sizeof (struct req_exec_amf_componentunregister); + req_exec_amf_componentunregister.header.id = MESSAGE_REQ_EXEC_AMF_COMPONENTUNREGISTER; + + req_exec_amf_componentunregister.source.fd = fd; + req_exec_amf_componentunregister.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + memcpy (&req_exec_amf_componentunregister.req_lib_amf_componentunregister, + req_lib_amf_componentunregister, + sizeof (struct req_lib_amf_componentunregister)); + + component = findComponent (&req_lib_amf_componentunregister->compName); + if (component && component->registered && component->local) { + component->probableCause = SA_AMF_NOT_RESPONDING; + } + iovecs[0].iov_base = &req_exec_amf_componentunregister; + iovecs[0].iov_len = sizeof (req_exec_amf_componentunregister); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_amf_readinessstateget (int fd, void *message) +{ + struct req_amf_readinessstateget *req_amf_readinessstateget = (struct req_amf_readinessstateget *)message; + struct res_amf_readinessstateget res_amf_readinessstateget; + struct saAmfComponent *component; + + log_printf (LOG_LEVEL_DEBUG, "got request to return readiness state\n"); + res_amf_readinessstateget.header.magic = MESSAGE_MAGIC; + res_amf_readinessstateget.header.id = MESSAGE_RES_AMF_READINESSSTATEGET; + res_amf_readinessstateget.header.size = sizeof (struct res_amf_readinessstateget); + res_amf_readinessstateget.error = SA_ERR_NOT_EXIST; + + component = findComponent (&req_amf_readinessstateget->compName); + log_printf (LOG_LEVEL_DEBUG, "readinessstateget: found component %p\n", component); + if (component) { + memcpy (&res_amf_readinessstateget.readinessState, + &component->currentReadinessState, sizeof (SaAmfReadinessStateT)); + res_amf_readinessstateget.error = SA_OK; + } + libais_send_response (fd, &res_amf_readinessstateget, sizeof (struct res_amf_readinessstateget)); + return (0); +} + +static int message_handler_req_amf_hastateget (int fd, void *message) +{ + struct req_amf_hastateget *req_amf_hastateget = (struct req_amf_hastateget *)message; + struct res_amf_hastateget res_amf_hastateget; + struct saAmfComponent *component; + + res_amf_hastateget.header.magic = MESSAGE_MAGIC; + res_amf_hastateget.header.id = MESSAGE_RES_AMF_HASTATEGET; + res_amf_hastateget.header.size = sizeof (struct res_amf_hastateget); + res_amf_hastateget.error = SA_ERR_NOT_EXIST; + + component = findComponentInProtectionGroup (&req_amf_hastateget->csiName, &req_amf_hastateget->compName); + + if (component) { + memcpy (&res_amf_hastateget.haState, + &component->currentHAState, sizeof (SaAmfHAStateT)); + res_amf_hastateget.error = SA_OK; + } + libais_send_response (fd, &res_amf_hastateget, sizeof (struct res_amf_hastateget)); + return (0); +} + +static int message_handler_req_amf_protectiongrouptrackstart (int fd, void *message) +{ + struct req_amf_protectiongrouptrackstart *req_amf_protectiongrouptrackstart = (struct req_amf_protectiongrouptrackstart *)message; + struct res_amf_protectiongrouptrackstart res_amf_protectiongrouptrackstart; + struct libamf_ci_trackentry *track = 0; + int i; + struct saAmfProtectionGroup *amfProtectionGroup; + + amfProtectionGroup = findProtectionGroup (&req_amf_protectiongrouptrackstart->csiName); + + if (amfProtectionGroup) { + log_printf (LOG_LEVEL_DEBUG, "protectiongrouptrackstart: Got valid track start on CSI: %s.\n", getSaNameT (&req_amf_protectiongrouptrackstart->csiName)); + for (i = 0; i < connections[fd].ais_ci.u.libamf_ci.trackEntries; i++) { + if (connections[fd].ais_ci.u.libamf_ci.tracks[i].active == 0) { + track = &connections[fd].ais_ci.u.libamf_ci.tracks[i]; + break; + } + } + if (track == 0) { + grow_amf_track_table (fd, 1); + track = &connections[fd].ais_ci.u.libamf_ci.tracks[i]; + } + + track->active = 1; + track->trackFlags = req_amf_protectiongrouptrackstart->trackFlags; + track->notificationBufferAddress = req_amf_protectiongrouptrackstart->notificationBufferAddress; + memcpy (&track->csiName, + &req_amf_protectiongrouptrackstart->csiName, sizeof (SaNameT)); + + /* + * If SA_TRACK_CURRENT is specified, write out all current connections + */ + } else { + log_printf (LOG_LEVEL_DEBUG, "invalid track start, csi not registered with system.\n"); + } + + res_amf_protectiongrouptrackstart.header.magic = MESSAGE_MAGIC; + res_amf_protectiongrouptrackstart.header.id = MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTART; + res_amf_protectiongrouptrackstart.header.size = sizeof (struct res_amf_protectiongrouptrackstart); + res_amf_protectiongrouptrackstart.error = SA_ERR_NOT_EXIST; + + if (amfProtectionGroup) { + res_amf_protectiongrouptrackstart.error = SA_OK; + } + libais_send_response (fd, &res_amf_protectiongrouptrackstart, + sizeof (struct res_amf_protectiongrouptrackstart)); + + if (amfProtectionGroup && + req_amf_protectiongrouptrackstart->trackFlags & SA_TRACK_CURRENT) { + + sendProtectionGroupNotification (fd, + track->notificationBufferAddress, + amfProtectionGroup, + 0, + 0, + track->trackFlags); + + track->trackFlags &= ~SA_TRACK_CURRENT; + } + return (0); +} + +static int message_handler_req_amf_protectiongrouptrackstop (int fd, void *message) +{ + struct req_amf_protectiongrouptrackstop *req_amf_protectiongrouptrackstop = (struct req_amf_protectiongrouptrackstop *)message; + struct res_amf_protectiongrouptrackstop res_amf_protectiongrouptrackstop; + struct libamf_ci_trackentry *track = 0; + int i; + + for (i = 0; i < connections[fd].ais_ci.u.libamf_ci.trackEntries; i++) { + if (SaNameTisNameT (&req_amf_protectiongrouptrackstop->csiName, + &connections[fd].ais_ci.u.libamf_ci.tracks[i].csiName)) { + + track = &connections[fd].ais_ci.u.libamf_ci.tracks[i]; + } + } + + if (track) { + log_printf (LOG_LEVEL_DEBUG, "protectiongrouptrackstop: Trackstop on CSI: %s\n", getSaNameT (&req_amf_protectiongrouptrackstop->csiName)); + memset (track, 0, sizeof (struct libamf_ci_trackentry)); + } + + res_amf_protectiongrouptrackstop.header.magic = MESSAGE_MAGIC; + res_amf_protectiongrouptrackstop.header.id = MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTOP; + res_amf_protectiongrouptrackstop.header.size = sizeof (struct res_amf_protectiongrouptrackstop); + res_amf_protectiongrouptrackstop.error = SA_ERR_NOT_EXIST; + + if (track) { + res_amf_protectiongrouptrackstop.error = SA_OK; + } + libais_send_response (fd, &res_amf_protectiongrouptrackstop, + sizeof (struct res_amf_protectiongrouptrackstop)); + + return (0); +} + +static int message_handler_req_amf_errorreport (int fd, void *message) +{ + struct req_lib_amf_errorreport *req_lib_amf_errorreport = (struct req_lib_amf_errorreport *)message; + struct req_exec_amf_errorreport req_exec_amf_errorreport; + + struct iovec iovecs[2]; + int result; + + req_exec_amf_errorreport.header.magic = MESSAGE_MAGIC; + req_exec_amf_errorreport.header.size = sizeof (struct req_exec_amf_errorreport); + req_exec_amf_errorreport.header.id = MESSAGE_REQ_EXEC_AMF_ERRORREPORT; + + req_exec_amf_errorreport.source.fd = fd; + req_exec_amf_errorreport.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + memcpy (&req_exec_amf_errorreport.req_lib_amf_errorreport, + req_lib_amf_errorreport, + sizeof (struct req_lib_amf_errorreport)); + + iovecs[0].iov_base = &req_exec_amf_errorreport; + iovecs[0].iov_len = sizeof (req_exec_amf_errorreport); +// iovecs[0].iov_len = sizeof (req_exec_amf_errorreport) - sizeof (req_lib_amf_errorreport); + +// iovecs[1].iov_base = &req_lib_amf_errorreport; +// iovecs[1].iov_len = sizeof (req_lib_amf_errorreport); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_amf_errorcancelall (int fd, void *message) +{ + struct req_lib_amf_errorcancelall *req_lib_amf_errorcancelall = (struct req_lib_amf_errorcancelall *)message; + struct req_exec_amf_errorcancelall req_exec_amf_errorcancelall; + + struct iovec iovecs[2]; + int result; + + req_exec_amf_errorcancelall.header.magic = MESSAGE_MAGIC; + req_exec_amf_errorcancelall.header.size = sizeof (struct req_exec_amf_errorcancelall); + req_exec_amf_errorcancelall.header.id = MESSAGE_REQ_EXEC_AMF_ERRORCANCELALL; + + req_exec_amf_errorcancelall.source.fd = fd; + req_exec_amf_errorcancelall.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + memcpy (&req_exec_amf_errorcancelall.req_lib_amf_errorcancelall, + req_lib_amf_errorcancelall, + sizeof (struct req_lib_amf_errorcancelall)); + + iovecs[0].iov_base = &req_exec_amf_errorcancelall; + iovecs[0].iov_len = sizeof (req_exec_amf_errorcancelall); +// iovecs[0].iov_len = sizeof (req_exec_amf_errorcancelall) - sizeof (req_lib_amf_errorcancelall); + +// iovecs[1].iov_base = &req_lib_amf_errorcancelall; +// iovecs[1].iov_len = sizeof (req_lib_amf_errorcancelall); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_amf_stoppingcomplete (int fd, void *message) +{ + struct req_amf_stoppingcomplete *req_amf_stoppingcomplete = (struct req_amf_stoppingcomplete *)message; + + int connection; + + log_printf (LOG_LEVEL_DEBUG, "handling stopping complete\n"); + connection = req_amf_response_get_connection (req_amf_stoppingcomplete->invocation); + connections[connection].component->currentReadinessState = connections[connection].component->newReadinessState; + + readinessStateSetCluster (connections[connection].component, SA_AMF_STOPPING); + + sendProtectionGroupNotifications (connections[connection].component, + SA_AMF_PROTECTION_GROUP_STATE_CHANGE); + +// This is part of dsm now +// readinessStateSetApi (connections[connection].component, SA_AMF_OUT_OF_SERVICE); + + return (0); +} + +void response_handler_healthcheckcallback (int connection, + struct req_amf_response *req_amf_response) { + + if (req_amf_response->error == SA_OK) { + log_printf (LOG_LEVEL_DEBUG, "setting healthcheck ok\n"); + connections[connection].component->healthcheck_outstanding = 0; + } +} + +static int message_handler_req_amf_response (int fd, void *message) +{ + struct req_amf_response *req_amf_response = (struct req_amf_response *)message; + int connection; + int interface; + + connection = req_amf_response_get_connection (req_amf_response->invocation); + interface = req_amf_response_get_interface (req_amf_response->invocation); + log_printf (LOG_LEVEL_DEBUG, "handling response connection %d interface %x\n", connection, interface); + switch (interface) { + case MESSAGE_REQ_AMF_RESPONSE_SAAMFHEALTHCHECKCALLBACK: + response_handler_healthcheckcallback (connection, req_amf_response); + break; + + case MESSAGE_REQ_AMF_RESPONSE_SAAMFREADINESSSTATESETCALLBACK: + response_handler_readinessstatesetcallback (connection, req_amf_response); + break; + + case MESSAGE_REQ_AMF_RESPONSE_SAAMFCSISETCALLBACK: + response_handler_csisetcallback (connection, req_amf_response); + break; + + case MESSAGE_REQ_AMF_RESPONSE_SAAMFCSIREMOVECALLBACK: + break; + + default: + // TODO + log_printf (LOG_LEVEL_ERROR, "invalid invocation value %x\n", req_amf_response->invocation); + break; + } + + return (0); +} + +static int message_handler_req_amf_componentcapabilitymodelget (int fd, void *message) +{ + struct req_amf_componentcapabilitymodelget *req_amf_componentcapabilitymodelget = (struct req_amf_componentcapabilitymodelget *)message; + struct res_amf_componentcapabilitymodelget res_amf_componentcapabilitymodelget; + struct saAmfComponent *component; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "componentcapabilitymodelget: Retrieve name %s.\n", getSaNameT (&req_amf_componentcapabilitymodelget->compName)); + component = findComponent (&req_amf_componentcapabilitymodelget->compName); + if (component && component->registered) { + memcpy (&res_amf_componentcapabilitymodelget.componentCapabilityModel, + &component->componentCapabilityModel, sizeof (SaAmfComponentCapabilityModelT)); + } else { + error = SA_ERR_NOT_EXIST; + } + + res_amf_componentcapabilitymodelget.header.magic = MESSAGE_MAGIC; + res_amf_componentcapabilitymodelget.header.size = sizeof (struct res_amf_componentcapabilitymodelget); + res_amf_componentcapabilitymodelget.header.id = MESSAGE_RES_AMF_COMPONENTCAPABILITYMODELGET; + res_amf_componentcapabilitymodelget.error = error; + libais_send_response (fd, &res_amf_componentcapabilitymodelget, sizeof (struct res_amf_componentcapabilitymodelget)); + + return (0); +} + diff --git a/exec/amf.h b/exec/amf.h index e69de29b..1713cbf3 100644 --- a/exec/amf.h +++ b/exec/amf.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 "../include/ais_msg.h" +#include "poll.h" +#include "parse.h" +#include "handlers.h" + +#ifndef AMF_H_DEFINED +#define AMF_H_DEFINED + +struct libamf_ci_trackentry { + int active; + SaUint8T trackFlags; + SaAmfProtectionGroupNotificationT *notificationBufferAddress; + SaNameT csiName; +}; + +struct libamf_ci { + struct libamf_ci_trackentry *tracks; + int trackEntries; +}; + +extern struct service_handler amf_service_handler; + +#endif /* AMF_H_DEFINED */ diff --git a/exec/ckpt.c b/exec/ckpt.c index e69de29b..f3a91e2a 100644 --- a/exec/ckpt.c +++ b/exec/ckpt.c @@ -0,0 +1,1638 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_msg.h" +#include "../include/list.h" +#include "../include/queue.h" +#include "poll.h" +#include "mempool.h" +#include "parse.h" +#include "main.h" +#include "print.h" +#include "gmi.h" + +DECLARE_LIST_INIT(checkpointListHead); + +DECLARE_LIST_INIT(checkpointIteratorListHead); + +static int ckptCheckpointApiFinalize (int fd); +static int ckptSectionIteratorApiFinalize (int fd); + +static int message_handler_req_exec_ckpt_checkpointopen (int fd, void *message); + +static int message_handler_req_exec_ckpt_checkpointclose (int fd, void *message); + +static int message_handler_req_exec_ckpt_checkpointunlink (int fd, void *message); + +static int message_handler_req_exec_ckpt_checkpointretentiondurationset (int fd, void *message); + +static int message_handler_req_exec_ckpt_sectioncreate (int fd, void *message); + +static int message_handler_req_exec_ckpt_sectiondelete (int fd, void *message); + +static int message_handler_req_exec_ckpt_sectionexpirationtimeset (int fd, void *message); + +static int message_handler_req_exec_ckpt_sectionwrite (int fd, void *message); + +static int message_handler_req_exec_ckpt_sectionoverwrite (int fd, void *message); + +static int message_handler_req_exec_ckpt_sectionread (int fd, void *message); + +static int message_handler_req_lib_ckpt_init (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpoint_init (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectioniterator_init (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointopen (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointopenasync (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointunlink (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointretentiondurationset (int fd, void *message); + +static int message_handler_req_lib_ckpt_activecheckpointset (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointstatusget (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectioncreate (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectiondelete (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectionexpirationtimeset (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectionwrite (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectionoverwrite (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectionread (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointsynchronize (int fd, void *message); + +static int message_handler_req_lib_ckpt_checkpointsyncronizeasync (int fd, void *message); + +static int message_handler_req_lib_ckpt_sectioniteratorinitialize (int fd, void *message); +static int message_handler_req_lib_ckpt_sectioniteratornext (int fd, void *message); + +static int ckptConfChg ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries) { + + return (0); +} + +int (*ckpt_libais_handler_fns[]) (int fd, void *) = { +}; + +/* + * TODO multinode not yet implemented + */ +int (*ckpt_aisexec_handler_fns[]) (int fd, void *) = { +}; + +/* + * exported service + */ +struct service_handler ckpt_service_handler = { + libais_handler_fns: ckpt_libais_handler_fns, + libais_handler_fns_count: sizeof (ckpt_libais_handler_fns) / sizeof (int (*)), + aisexec_handler_fns: ckpt_aisexec_handler_fns , + aisexec_handler_fns_count: sizeof (ckpt_aisexec_handler_fns) / sizeof (int (*)), + confchg_fn: 0, /* ckpt service handler is not distributed */ + libais_init_fn: message_handler_req_lib_ckpt_init, + libais_exit_fn: 0, + aisexec_init_fn: 0 +}; + +static int (*ckpt_checkpoint_libais_handler_fns[]) (int fd, void *) = { + message_handler_req_lib_ckpt_checkpointopen, + message_handler_req_lib_ckpt_checkpointopenasync, + message_handler_req_lib_ckpt_checkpointunlink, + message_handler_req_lib_ckpt_checkpointretentiondurationset, + message_handler_req_lib_ckpt_activecheckpointset, + message_handler_req_lib_ckpt_checkpointstatusget, + message_handler_req_lib_ckpt_sectioncreate, + message_handler_req_lib_ckpt_sectiondelete, + message_handler_req_lib_ckpt_sectionexpirationtimeset, + message_handler_req_lib_ckpt_sectionwrite, + message_handler_req_lib_ckpt_sectionoverwrite, + message_handler_req_lib_ckpt_sectionread, + message_handler_req_lib_ckpt_checkpointsynchronize, + message_handler_req_lib_ckpt_checkpointsyncronizeasync +}; + +static int (*ckpt_checkpoint_aisexec_handler_fns[]) (int fd, void *) = { + message_handler_req_exec_ckpt_checkpointopen, + message_handler_req_exec_ckpt_checkpointclose, + message_handler_req_exec_ckpt_checkpointunlink, + message_handler_req_exec_ckpt_checkpointretentiondurationset, + message_handler_req_exec_ckpt_sectioncreate, + message_handler_req_exec_ckpt_sectiondelete, + message_handler_req_exec_ckpt_sectionexpirationtimeset, + message_handler_req_exec_ckpt_sectionwrite, + message_handler_req_exec_ckpt_sectionoverwrite, + message_handler_req_exec_ckpt_sectionread +}; + +struct service_handler ckpt_checkpoint_service_handler = { + libais_handler_fns: ckpt_checkpoint_libais_handler_fns, + libais_handler_fns_count: sizeof (ckpt_checkpoint_libais_handler_fns) / sizeof (int (*)), + aisexec_handler_fns: ckpt_checkpoint_aisexec_handler_fns , + aisexec_handler_fns_count: sizeof (ckpt_checkpoint_aisexec_handler_fns) / sizeof (int (*)), + confchg_fn: ckptConfChg, + libais_init_fn: message_handler_req_lib_ckpt_checkpoint_init, + libais_exit_fn: ckptCheckpointApiFinalize, + aisexec_init_fn: 0 +}; + +static int (*ckpt_sectioniterator_libais_handler_fns[]) (int fd, void *) = { + message_handler_req_lib_ckpt_sectioniteratorinitialize, + message_handler_req_lib_ckpt_sectioniteratornext +}; + +static int (*ckpt_sectioniterator_aisexec_handler_fns[]) (int fd, void *) = { +}; + +struct service_handler ckpt_sectioniterator_service_handler = { + libais_handler_fns: ckpt_sectioniterator_libais_handler_fns, + libais_handler_fns_count: sizeof (ckpt_sectioniterator_libais_handler_fns) / sizeof (int (*)), + aisexec_handler_fns: ckpt_sectioniterator_aisexec_handler_fns , + aisexec_handler_fns_count: sizeof (ckpt_sectioniterator_aisexec_handler_fns) / sizeof (int (*)), + confchg_fn: 0, /* Section Iterators are not distributed */ + libais_init_fn: message_handler_req_lib_ckpt_sectioniterator_init, + libais_exit_fn: ckptSectionIteratorApiFinalize, + aisexec_init_fn: 0 +}; + +static struct saCkptCheckpoint *findCheckpoint (SaNameT *name) +{ + struct list_head *checkpointList; + struct saCkptCheckpoint *checkpoint; + + for (checkpointList = checkpointListHead.next; + checkpointList != &checkpointListHead; + checkpointList = checkpointList->next) { + + checkpoint = list_entry (checkpointList, + struct saCkptCheckpoint, list); + + if (SaNameTisNameT (name, &checkpoint->name)) { + return (checkpoint); + } + } + return (0); +} + +static struct saCkptCheckpointSection *findCheckpointSection ( + struct saCkptCheckpoint *ckptCheckpoint, + char *id, + int idLen) +{ + struct list_head *checkpointSectionList; + struct saCkptCheckpointSection *ckptCheckpointSection; + + log_printf (LOG_LEVEL_DEBUG, "Finding checkpoint section id %s %d\n", id, idLen); + for (checkpointSectionList = ckptCheckpoint->checkpointSectionsListHead.next; + checkpointSectionList != &ckptCheckpoint->checkpointSectionsListHead; + checkpointSectionList = checkpointSectionList->next) { + + ckptCheckpointSection = list_entry (checkpointSectionList, + struct saCkptCheckpointSection, list); + + log_printf (LOG_LEVEL_DEBUG, "Checking section id %s %d\n", + ckptCheckpointSection->sectionDescriptor.sectionId.id, + ckptCheckpointSection->sectionDescriptor.sectionId.idLen); + + if (ckptCheckpointSection->sectionDescriptor.sectionId.idLen == idLen && + (memcmp (ckptCheckpointSection->sectionDescriptor.sectionId.id, + id, idLen) == 0)) { + + return (ckptCheckpointSection); + } + } + return 0; +} + +void sendCkptCheckpointClose (struct saCkptCheckpoint *checkpoint) { + struct req_exec_ckpt_checkpointclose req_exec_ckpt_checkpointclose; + struct iovec iovecs[2]; + int result; + + req_exec_ckpt_checkpointclose.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_checkpointclose.header.size = + sizeof (struct req_exec_ckpt_checkpointclose); + req_exec_ckpt_checkpointclose.header.id = MESSAGE_REQ_EXEC_CKPT_CHECKPOINTCLOSE; + + memcpy (&req_exec_ckpt_checkpointclose.checkpointName, + &checkpoint->name, + sizeof (SaNameT)); + + iovecs[0].iov_base = &req_exec_ckpt_checkpointclose; + iovecs[0].iov_len = sizeof (req_exec_ckpt_checkpointclose); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); +} + +static int ckptCheckpointApiFinalize (int fd) +{ + /* + * close checkpoint opened from this fd + */ + if (connections[fd].service == SOCKET_SERVICE_CKPT_CHECKPOINT && + connections[fd].ais_ci.u.libckpt_ci.checkpoint) { +log_printf (LOG_LEVEL_DEBUG, "APIFinalize fd is %d %s\n", fd, getSaNameT (&connections[fd].ais_ci.u.libckpt_ci.checkpoint->name)); + + sendCkptCheckpointClose (connections[fd].ais_ci.u.libckpt_ci.checkpoint); + } + return (0); +} + +static int ckptSectionIteratorApiFinalize (int fd) { + /* + * If section iterator connection, unlink from list and free section iterator data + */ + if (connections[fd].service == SOCKET_SERVICE_CKPT_SECTIONITERATOR) { + log_printf (LOG_LEVEL_DEBUG, "freeing section iterator\n"); + if (connections[fd].ais_ci.u.libckpt_ci.sectionIterator.sectionIteratorEntries) { + free (connections[fd].ais_ci.u.libckpt_ci.sectionIterator.sectionIteratorEntries); + } + list_del (&connections[fd].ais_ci.u.libckpt_ci.sectionIterator.list); + } + + return (0); +} + +static int message_handler_req_exec_ckpt_checkpointopen (int fd, void *message) +{ + struct req_exec_ckpt_checkpointopen *req_exec_ckpt_checkpointopen = (struct req_exec_ckpt_checkpointopen *)message; + struct req_lib_ckpt_checkpointopen *req_lib_ckpt_checkpointopen = (struct req_lib_ckpt_checkpointopen *)&req_exec_ckpt_checkpointopen->req_lib_ckpt_checkpointopen; + struct res_lib_ckpt_checkpointopen res_lib_ckpt_checkpointopen; + + struct saCkptCheckpoint *ckptCheckpoint = 0; + struct saCkptCheckpointSection *ckptCheckpointSection = 0; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Executive request to open checkpoint %p\n", req_exec_ckpt_checkpointopen); + + ckptCheckpoint = findCheckpoint (&req_lib_ckpt_checkpointopen->checkpointName); + + /* + * If checkpoint doesn't exist, create one + */ + if (ckptCheckpoint == 0) { + ckptCheckpoint = malloc (sizeof (struct saCkptCheckpoint)); + if (ckptCheckpoint == 0) { + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + + ckptCheckpointSection = malloc (sizeof (struct saCkptCheckpointSection)); + if (ckptCheckpointSection == 0) { + free (ckptCheckpoint); + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + + memcpy (&ckptCheckpoint->name, + &req_lib_ckpt_checkpointopen->checkpointName, + sizeof (SaNameT)); + memcpy (&ckptCheckpoint->checkpointCreationAttributes, + &req_lib_ckpt_checkpointopen->checkpointCreationAttributes, + sizeof (SaCkptCheckpointCreationAttributesT)); + ckptCheckpoint->unlinked = 0; + list_init (&ckptCheckpoint->list); + list_init (&ckptCheckpoint->checkpointSectionsListHead); + list_add (&ckptCheckpoint->list, &checkpointListHead); + ckptCheckpoint->referenceCount = 0; + + /* + * Add in default checkpoint section + */ + list_init (&ckptCheckpointSection->list); + list_add (&ckptCheckpointSection->list, &ckptCheckpoint->checkpointSectionsListHead); + ckptCheckpointSection->sectionDescriptor.expirationTime = 0xFFFFFFFF; //SA_END_TIME; + + /* + * Default section id + */ + ckptCheckpointSection->sectionDescriptor.sectionId.id = 0; + ckptCheckpointSection->sectionDescriptor.sectionId.idLen = 0; + ckptCheckpointSection->sectionDescriptor.sectionSize = 0; + ckptCheckpointSection->sectionDescriptor.expirationTime = 0xffffffff; /* SA_END_TIME */ + ckptCheckpointSection->sectionDescriptor.sectionState = SA_CKPT_SECTION_VALID; + ckptCheckpointSection->sectionDescriptor.lastUpdate = 0; // current time + ckptCheckpointSection->sectionData = 0; + } + + /* + * If the checkpoint has been unlinked, it is an invalid name + */ + if (ckptCheckpoint->unlinked) { + error = SA_ERR_INVALID_PARAM; /* Is this the correct return ? */ + goto error_exit; + } + + /* + * Setup connection information and mark checkpoint as referenced + */ + log_printf (LOG_LEVEL_DEBUG, "CHECKPOINT opened fd %d is %p\n", fd, ckptCheckpoint); + ckptCheckpoint->referenceCount += 1; + + /* + * Send error result to CKPT library + */ +error_exit: + /* + * If this node was the source of the message, respond to this node + */ + if (req_exec_ckpt_checkpointopen->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + connections[req_exec_ckpt_checkpointopen->source.fd].ais_ci.u.libckpt_ci.checkpoint = ckptCheckpoint; + connections[req_exec_ckpt_checkpointopen->source.fd].ais_ci.u.libckpt_ci.checkpointOpenFlags = req_lib_ckpt_checkpointopen->checkpointOpenFlags; + res_lib_ckpt_checkpointopen.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_checkpointopen.header.size = sizeof (struct res_lib_ckpt_checkpointopen); + res_lib_ckpt_checkpointopen.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTOPEN; + res_lib_ckpt_checkpointopen.error = error; + + libais_send_response (req_exec_ckpt_checkpointopen->source.fd, &res_lib_ckpt_checkpointopen, + sizeof (struct res_lib_ckpt_checkpointopen)); + } + +// return (error == SA_OK ? 0 : -1); + return (0); +} + +extern int message_handler_req_exec_ckpt_checkpointclose (int fd, void *message) +{ + struct req_exec_ckpt_checkpointclose *req_exec_ckpt_checkpointclose = (struct req_exec_ckpt_checkpointclose *)message; + struct saCkptCheckpoint *checkpoint = 0; + + log_printf (LOG_LEVEL_DEBUG, "Got EXEC request to close checkpoint %s\n", getSaNameT (&req_exec_ckpt_checkpointclose->checkpointName)); + + checkpoint = findCheckpoint (&req_exec_ckpt_checkpointclose->checkpointName); + if (checkpoint == 0) { + return (0); + } + + checkpoint->referenceCount--; + log_printf (LOG_LEVEL_DEBUG, "disconnect called, new CKPT ref count is %d\n", + checkpoint->referenceCount); + + /* + * If checkpoint has been unlinked and this is the last reference, delete it + */ + if (checkpoint->unlinked && checkpoint->referenceCount == 0) { + log_printf (LOG_LEVEL_DEBUG, "Unlinking checkpoint.\n"); + list_del (&checkpoint->list); + free (checkpoint); + } else + if (checkpoint->referenceCount == 0) { + // TODO Start retention duration timer if reference count is 0 + // and checkpoint has not been unlinked + } + + return (0); +} + +static int message_handler_req_exec_ckpt_checkpointunlink (int fd, void *message) +{ + struct req_exec_ckpt_checkpointunlink *req_exec_ckpt_checkpointunlink = (struct req_exec_ckpt_checkpointunlink *)message; + + struct req_lib_ckpt_checkpointunlink *req_lib_ckpt_checkpointunlink = (struct req_lib_ckpt_checkpointunlink *)&req_exec_ckpt_checkpointunlink->req_lib_ckpt_checkpointunlink; + struct res_lib_ckpt_checkpointunlink res_lib_ckpt_checkpointunlink; + struct saCkptCheckpoint *ckptCheckpoint = 0; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Got EXEC request to unlink checkpoint %p\n", req_exec_ckpt_checkpointunlink); + ckptCheckpoint = findCheckpoint (&req_lib_ckpt_checkpointunlink->checkpointName); + if (ckptCheckpoint == 0) { +printf ("invalid checkpoint name\n"); + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + if (ckptCheckpoint->unlinked) { + error = SA_ERR_INVALID_PARAM; + goto error_exit; + } + ckptCheckpoint->unlinked = 1; + /* + * Immediately delete entry if reference count is zero + */ + if (ckptCheckpoint->referenceCount == 0) { + list_del (&ckptCheckpoint->list); + free (ckptCheckpoint); + } + +error_exit: + /* + * If this node was the source of the message, respond to this node + */ + if (req_exec_ckpt_checkpointunlink->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_checkpointunlink.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_checkpointunlink.header.size = sizeof (struct res_lib_ckpt_checkpointunlink); + res_lib_ckpt_checkpointunlink.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTUNLINK; + res_lib_ckpt_checkpointunlink.error = error; + libais_send_response (req_exec_ckpt_checkpointunlink->source.fd, &res_lib_ckpt_checkpointunlink, + sizeof (struct res_lib_ckpt_checkpointunlink)); + } + return (0); +} + +static int message_handler_req_exec_ckpt_checkpointretentiondurationset (int fd, void *message) +{ + struct req_exec_ckpt_checkpointretentiondurationset *req_exec_ckpt_checkpointretentiondurationset = (struct req_exec_ckpt_checkpointretentiondurationset *)message; + struct saCkptCheckpoint *checkpoint; + + log_printf (LOG_LEVEL_DEBUG, "Got EXEC request to set retention duratione checkpoint %p\n", req_exec_ckpt_checkpointretentiondurationset); + + checkpoint = findCheckpoint (&req_exec_ckpt_checkpointretentiondurationset->checkpointName); + if (checkpoint) { + log_printf (LOG_LEVEL_DEBUG, "setting retention duration\n"); + checkpoint->checkpointCreationAttributes.retentionDuration = req_exec_ckpt_checkpointretentiondurationset->retentionDuration; + } + + return (0); +} + +static int message_handler_req_exec_ckpt_sectioncreate (int fd, void *message) { + struct req_exec_ckpt_sectioncreate *req_exec_ckpt_sectioncreate = (struct req_exec_ckpt_sectioncreate *)message; + struct req_lib_ckpt_sectioncreate *req_lib_ckpt_sectioncreate = (struct req_lib_ckpt_sectioncreate *)&req_exec_ckpt_sectioncreate->req_lib_ckpt_sectioncreate; + struct res_lib_ckpt_sectioncreate res_lib_ckpt_sectioncreate; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection; + void *initialData; + void *sectionId; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Executive request to create a checkpoint section.\n"); + ckptCheckpoint = findCheckpoint (&req_exec_ckpt_sectioncreate->checkpointName); + if (ckptCheckpoint == 0) { + error = SA_ERR_SYSTEM; // TODO find the right error for this + goto error_exit; + } + + /* + * Determine if user-specified checkpoint ID already exists + */ + ckptCheckpointSection = findCheckpointSection (ckptCheckpoint, + ((char *)req_lib_ckpt_sectioncreate) + sizeof (struct req_lib_ckpt_sectioncreate), + req_lib_ckpt_sectioncreate->idLen); + if (ckptCheckpointSection) { + error = SA_ERR_EXIST; + goto error_exit; + } + + /* + * Allocate checkpoint section + */ + ckptCheckpointSection = malloc (sizeof (struct saCkptCheckpointSection)); + if (ckptCheckpointSection == 0) { + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + /* + * Allocate checkpoint section data + */ + initialData = malloc (req_lib_ckpt_sectioncreate->initialDataSize); + if (initialData == 0) { + free (ckptCheckpointSection); + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + /* + * Allocate checkpoint section id + */ + sectionId = malloc (req_lib_ckpt_sectioncreate->idLen); + if (sectionId == 0) { + free (ckptCheckpointSection); + free (initialData); + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + + /* + * Copy checkpoint section and section ID + */ + memcpy (sectionId, ((char *)req_lib_ckpt_sectioncreate) + sizeof (struct req_lib_ckpt_sectioncreate), + req_lib_ckpt_sectioncreate->idLen); + + memcpy (initialData, + ((char *)req_lib_ckpt_sectioncreate) + + sizeof (struct req_lib_ckpt_sectioncreate) + + req_lib_ckpt_sectioncreate->idLen, + req_lib_ckpt_sectioncreate->initialDataSize); + + /* + * Configure checkpoint section + */ + ckptCheckpointSection->sectionDescriptor.expirationTime = req_lib_ckpt_sectioncreate->expirationTime; + ckptCheckpointSection->sectionDescriptor.sectionId.id = sectionId; + ckptCheckpointSection->sectionDescriptor.sectionId.idLen = req_lib_ckpt_sectioncreate->idLen; + ckptCheckpointSection->sectionDescriptor.sectionSize = req_lib_ckpt_sectioncreate->initialDataSize; + ckptCheckpointSection->sectionDescriptor.sectionState = SA_CKPT_SECTION_VALID; + ckptCheckpointSection->sectionDescriptor.lastUpdate = 0; // TODO current time + ckptCheckpointSection->sectionData = initialData; + + /* + * Add checkpoint section to checkpoint + */ + list_init (&ckptCheckpointSection->list); + list_add (&ckptCheckpointSection->list, &ckptCheckpoint->checkpointSectionsListHead); + +error_exit: + if (req_exec_ckpt_sectioncreate->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_sectioncreate.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectioncreate.header.size = sizeof (struct res_lib_ckpt_sectioncreate); + res_lib_ckpt_sectioncreate.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONCREATE; + res_lib_ckpt_sectioncreate.error = error; + + libais_send_response (req_exec_ckpt_sectioncreate->source.fd, + &res_lib_ckpt_sectioncreate, + sizeof (struct res_lib_ckpt_sectioncreate)); + } + return (0); +} + +static int message_handler_req_exec_ckpt_sectiondelete (int fd, void *message) { + struct req_exec_ckpt_sectiondelete *req_exec_ckpt_sectiondelete = (struct req_exec_ckpt_sectiondelete *)message; + struct req_lib_ckpt_sectiondelete *req_lib_ckpt_sectiondelete = (struct req_lib_ckpt_sectiondelete *)&req_exec_ckpt_sectiondelete->req_lib_ckpt_sectiondelete; + struct res_lib_ckpt_sectiondelete res_lib_ckpt_sectiondelete; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection; + SaErrorT error = SA_OK; + + ckptCheckpoint = findCheckpoint (&req_exec_ckpt_sectiondelete->checkpointName); + if (ckptCheckpoint == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Determine if the user is trying to delete the default section + */ + if (req_lib_ckpt_sectiondelete->idLen == 0) { + error = SA_ERR_INVALID_PARAM; + goto error_exit; + } + + /* + * Find checkpoint section to be deleted + */ + ckptCheckpointSection = findCheckpointSection (ckptCheckpoint, + ((char *)(req_lib_ckpt_sectiondelete) + sizeof (struct req_lib_ckpt_sectiondelete)), + req_lib_ckpt_sectiondelete->idLen); + if (ckptCheckpointSection == 0) { +printf ("section not found\n"); + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Delete checkpoint section + */ + list_del (&ckptCheckpointSection->list); + free (ckptCheckpointSection->sectionDescriptor.sectionId.id); + free (ckptCheckpointSection->sectionData); + free (ckptCheckpointSection); + + /* + * return result to CKPT library + */ +error_exit: + if (req_exec_ckpt_sectiondelete->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_sectiondelete.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectiondelete.header.size = sizeof (struct res_lib_ckpt_sectiondelete); + res_lib_ckpt_sectiondelete.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONDELETE; + res_lib_ckpt_sectiondelete.error = error; + + libais_send_response (req_exec_ckpt_sectiondelete->source.fd, + &res_lib_ckpt_sectiondelete, + sizeof (struct res_lib_ckpt_sectiondelete)); + } + return (0); +} + +static int message_handler_req_exec_ckpt_sectionexpirationtimeset (int fd, void *message) { + struct req_exec_ckpt_sectionexpirationtimeset *req_exec_ckpt_sectionexpirationtimeset = (struct req_exec_ckpt_sectionexpirationtimeset *)message; + struct req_lib_ckpt_sectionexpirationtimeset *req_lib_ckpt_sectionexpirationtimeset = (struct req_lib_ckpt_sectionexpirationtimeset *)&req_exec_ckpt_sectionexpirationtimeset->req_lib_ckpt_sectionexpirationtimeset; + struct res_lib_ckpt_sectionexpirationtimeset res_lib_ckpt_sectionexpirationtimeset; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Executive request to set section expiratoin time\n"); + ckptCheckpoint = findCheckpoint (&req_exec_ckpt_sectionexpirationtimeset->checkpointName); + if (ckptCheckpoint == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Determine if the user is trying to set expiration time for the default section + */ + if (req_lib_ckpt_sectionexpirationtimeset->idLen == 0) { + error = SA_ERR_INVALID_PARAM; + goto error_exit; + } + + /* + * Find checkpoint section that expiration time should be set for + */ + ckptCheckpointSection = findCheckpointSection (ckptCheckpoint, + ((char *)req_lib_ckpt_sectionexpirationtimeset) + + sizeof (struct req_lib_ckpt_sectionexpirationtimeset), + req_lib_ckpt_sectionexpirationtimeset->idLen); + + if (ckptCheckpointSection == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + ckptCheckpointSection->sectionDescriptor.expirationTime = req_lib_ckpt_sectionexpirationtimeset->expirationTime; + +error_exit: + if (req_exec_ckpt_sectionexpirationtimeset->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_sectionexpirationtimeset.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionexpirationtimeset.header.size = sizeof (struct res_lib_ckpt_sectionexpirationtimeset); + res_lib_ckpt_sectionexpirationtimeset.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONEXPIRATIONTIMESET; + res_lib_ckpt_sectionexpirationtimeset.error = error; + + libais_send_response (req_exec_ckpt_sectionexpirationtimeset->source.fd, + &res_lib_ckpt_sectionexpirationtimeset, + sizeof (struct res_lib_ckpt_sectionexpirationtimeset)); + } + return (0); +} + +int exec_section_write = 0; +static int message_handler_req_exec_ckpt_sectionwrite (int fd, void *message) { + struct req_exec_ckpt_sectionwrite *req_exec_ckpt_sectionwrite = (struct req_exec_ckpt_sectionwrite *)message; + struct req_lib_ckpt_sectionwrite *req_lib_ckpt_sectionwrite = (struct req_lib_ckpt_sectionwrite *)&req_exec_ckpt_sectionwrite->req_lib_ckpt_sectionwrite; + struct res_lib_ckpt_sectionwrite res_lib_ckpt_sectionwrite; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection; + int sizeRequired; + void *sectionData; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Executive request to section write. %d\n", exec_section_write++); + ckptCheckpoint = findCheckpoint (&req_exec_ckpt_sectionwrite->checkpointName); + if (ckptCheckpoint == 0) { +printf ("can't find checkpoint\n"); // TODO + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + +//printf ("writing checkpoint section is %s\n", ((char *)req_lib_ckpt_sectionwrite) + sizeof (struct req_lib_ckpt_sectionwrite)); + /* + * Find checkpoint section to be written + */ + ckptCheckpointSection = findCheckpointSection (ckptCheckpoint, + ((char *)req_lib_ckpt_sectionwrite) + sizeof (struct req_lib_ckpt_sectionwrite), + req_lib_ckpt_sectionwrite->idLen); + if (ckptCheckpointSection == 0) { +printf ("CANT FIND SECTION '%s'\n", + ((char *)req_lib_ckpt_sectionwrite) + sizeof (struct req_lib_ckpt_sectionwrite)); + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * If write would extend past end of section data, enlarge section + */ + sizeRequired = req_lib_ckpt_sectionwrite->dataOffset + req_lib_ckpt_sectionwrite->dataSize; + if (sizeRequired > ckptCheckpointSection->sectionDescriptor.sectionSize) { +printf ("reallocating data\n"); + sectionData = realloc (ckptCheckpointSection->sectionData, sizeRequired); + if (sectionData == 0) { + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + + /* + * Install new section data + */ + ckptCheckpointSection->sectionData = sectionData; + ckptCheckpointSection->sectionDescriptor.sectionSize = sizeRequired; + } + + /* + * Write checkpoint section to section data + */ + if (req_lib_ckpt_sectionwrite->dataSize > 0) { + char *sd; + int *val; + val = ckptCheckpointSection->sectionData; + sd = (char *)ckptCheckpointSection->sectionData; + memcpy (&sd[req_lib_ckpt_sectionwrite->dataOffset], + ((char *)req_exec_ckpt_sectionwrite) + sizeof (struct req_exec_ckpt_sectionwrite) + + req_lib_ckpt_sectionwrite->idLen, + req_lib_ckpt_sectionwrite->dataSize); + } + /* + * Write write response to CKPT library + */ +error_exit: + if (req_exec_ckpt_sectionwrite->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_sectionwrite.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionwrite.header.size = sizeof (struct res_lib_ckpt_sectionwrite); + res_lib_ckpt_sectionwrite.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONWRITE; + res_lib_ckpt_sectionwrite.error = error; + + libais_send_response (req_exec_ckpt_sectionwrite->source.fd, + &res_lib_ckpt_sectionwrite, + sizeof (struct res_lib_ckpt_sectionwrite)); + } + + return (0); +} + +static int message_handler_req_exec_ckpt_sectionoverwrite (int fd, void *message) { + struct req_exec_ckpt_sectionoverwrite *req_exec_ckpt_sectionoverwrite = (struct req_exec_ckpt_sectionoverwrite *)message; + struct req_lib_ckpt_sectionoverwrite *req_lib_ckpt_sectionoverwrite = (struct req_lib_ckpt_sectionoverwrite *)&req_exec_ckpt_sectionoverwrite->req_lib_ckpt_sectionoverwrite; + struct res_lib_ckpt_sectionoverwrite res_lib_ckpt_sectionoverwrite; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection; + void *sectionData; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Executive request to section overwrite.\n"); + ckptCheckpoint = findCheckpoint (&req_exec_ckpt_sectionoverwrite->checkpointName); + if (ckptCheckpoint == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Find checkpoint section to be overwritten + */ + ckptCheckpointSection = findCheckpointSection (ckptCheckpoint, + ((char *)req_lib_ckpt_sectionoverwrite) + + sizeof (struct req_lib_ckpt_sectionoverwrite), + req_lib_ckpt_sectionoverwrite->idLen); + if (ckptCheckpointSection == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Allocate checkpoint section data + */ + sectionData = malloc (req_lib_ckpt_sectionoverwrite->dataSize); + if (sectionData == 0) { + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + + memcpy (sectionData, + ((char *)req_lib_ckpt_sectionoverwrite) + + sizeof (struct req_lib_ckpt_sectionoverwrite) + + req_lib_ckpt_sectionoverwrite->idLen, + req_lib_ckpt_sectionoverwrite->dataSize); + + /* + * release old checkpoint section data + */ + free (ckptCheckpointSection->sectionData); + + /* + * Install overwritten checkpoint section data + */ + ckptCheckpointSection->sectionDescriptor.sectionSize = req_lib_ckpt_sectionoverwrite->dataSize; + ckptCheckpointSection->sectionDescriptor.sectionState = SA_CKPT_SECTION_VALID; + ckptCheckpointSection->sectionDescriptor.lastUpdate = 0; // TODO current time + ckptCheckpointSection->sectionData = sectionData; + + /* + * return result to CKPT library + */ +error_exit: + if (req_exec_ckpt_sectionoverwrite->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_sectionoverwrite.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionoverwrite.header.size = sizeof (struct res_lib_ckpt_sectionoverwrite); + res_lib_ckpt_sectionoverwrite.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONOVERWRITE; + res_lib_ckpt_sectionoverwrite.error = error; + + libais_send_response (req_exec_ckpt_sectionoverwrite->source.fd, + &res_lib_ckpt_sectionoverwrite, + sizeof (struct res_lib_ckpt_sectionoverwrite)); + } + return (0); +} +static int message_handler_req_exec_ckpt_sectionread (int fd, void *message) { + struct req_exec_ckpt_sectionread *req_exec_ckpt_sectionread = (struct req_exec_ckpt_sectionread *)message; + struct req_lib_ckpt_sectionread *req_lib_ckpt_sectionread = (struct req_lib_ckpt_sectionread *)&req_exec_ckpt_sectionread->req_lib_ckpt_sectionread; + struct res_lib_ckpt_sectionread res_lib_ckpt_sectionread; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection = 0; + int sectionSize = 0; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "Executive request for section read.\n"); + + ckptCheckpoint = findCheckpoint (&req_exec_ckpt_sectionread->checkpointName); + if (ckptCheckpoint == 0) { + error = SA_ERR_SYSTEM; // TODO find the right error for this + goto error_exit; + } + + /* + * Find checkpoint section to be read + */ + ckptCheckpointSection = findCheckpointSection (ckptCheckpoint, + ((char *)req_lib_ckpt_sectionread) + + sizeof (struct req_lib_ckpt_sectionread), + req_lib_ckpt_sectionread->idLen); + if (ckptCheckpointSection == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Determine the section size + */ + sectionSize = ckptCheckpointSection->sectionDescriptor.sectionSize - + req_lib_ckpt_sectionread->dataOffset; + + /* + * If the library has less space available then can be sent from the + * section, reduce bytes sent to library to max requested + */ + if (sectionSize > req_lib_ckpt_sectionread->dataSize) { + sectionSize = req_lib_ckpt_sectionread->dataSize; + } + + /* + * If dataOffset is past end of data, return INVALID PARAM + */ + if (req_lib_ckpt_sectionread->dataOffset > sectionSize) { + sectionSize = 0; + error = SA_ERR_INVALID_PARAM; + goto error_exit; + } + + /* + * Write read response to CKPT library + */ +error_exit: + if (req_exec_ckpt_sectionread->source.in_addr.s_addr == this_ip.sin_addr.s_addr) { + res_lib_ckpt_sectionread.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionread.header.size = sizeof (struct res_lib_ckpt_sectionread) + sectionSize; + res_lib_ckpt_sectionread.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONREAD; + res_lib_ckpt_sectionread.error = error; + + libais_send_response (req_exec_ckpt_sectionread->source.fd, + &res_lib_ckpt_sectionread, + sizeof (struct res_lib_ckpt_sectionread)); + + /* + * Write checkpoint to CKPT library section if section has data + */ + if (sectionSize) { + char *sd; + sd = (char *)ckptCheckpointSection->sectionData; + libais_send_response (req_exec_ckpt_sectionread->source.fd, + &sd[req_lib_ckpt_sectionread->dataOffset], + sectionSize); + } + } + return (0); +} + +static int message_handler_req_lib_ckpt_init (int fd, void *message) +{ + struct res_lib_init res_lib_init; + SaErrorT error = SA_ERR_SECURITY; + + log_printf (LOG_LEVEL_DEBUG, "Got request to initialize CKPT.\n"); + + if (connections[fd].authenticated) { + connections[fd].service = SOCKET_SERVICE_CKPT; + error = SA_OK; + } + + res_lib_init.header.magic = MESSAGE_MAGIC; + res_lib_init.header.size = sizeof (struct res_lib_init); + res_lib_init.header.id = MESSAGE_RES_INIT; + res_lib_init.error = error; + + libais_send_response (fd, &res_lib_init, sizeof (res_lib_init)); + + if (connections[fd].authenticated) { + return (0); + } + return (-1); +} + +static int message_handler_req_lib_ckpt_checkpoint_init (int fd, void *message) +{ + struct res_lib_init res_lib_init; + SaErrorT error = SA_ERR_SECURITY; + + log_printf (LOG_LEVEL_DEBUG, "Got request to initialize CKPT checkpoint.\n"); + + if (connections[fd].authenticated) { + connections[fd].service = SOCKET_SERVICE_CKPT_CHECKPOINT; + connections[fd].ais_ci.u.libckpt_ci.checkpoint = 0; + connections[fd].ais_ci.u.libckpt_ci.checkpointOpenFlags = 0; + error = SA_OK; + } + + res_lib_init.header.magic = MESSAGE_MAGIC; + res_lib_init.header.size = sizeof (struct res_lib_init); + res_lib_init.header.id = MESSAGE_RES_INIT; + res_lib_init.error = error; + + libais_send_response (fd, &res_lib_init, sizeof (res_lib_init)); + + if (connections[fd].authenticated) { + return (0); + } + return (-1); +} + +static int message_handler_req_lib_ckpt_sectioniterator_init (int fd, void *message) +{ + struct res_lib_init res_lib_init; + SaErrorT error = SA_ERR_SECURITY; + + log_printf (LOG_LEVEL_DEBUG, "Got request to initialize CKPT section iterator.\n"); + + if (connections[fd].authenticated) { + connections[fd].service = SOCKET_SERVICE_CKPT_SECTIONITERATOR; + list_init (&connections[fd].ais_ci.u.libckpt_ci.sectionIterator.list); + connections[fd].ais_ci.u.libckpt_ci.sectionIterator.sectionIteratorEntries = 0; + connections[fd].ais_ci.u.libckpt_ci.sectionIterator.iteratorCount = 0; + connections[fd].ais_ci.u.libckpt_ci.sectionIterator.iteratorPos = 0; + list_add (&connections[fd].ais_ci.u.libckpt_ci.sectionIterator.list, + &checkpointIteratorListHead); + error = SA_OK; + } + + res_lib_init.header.magic = MESSAGE_MAGIC; + res_lib_init.header.size = sizeof (struct res_lib_init); + res_lib_init.header.id = MESSAGE_RES_INIT; + res_lib_init.error = error; + + libais_send_response (fd, &res_lib_init, sizeof (res_lib_init)); + + if (connections[fd].authenticated) { + return (0); + } + return (-1); +} + +static int message_handler_req_lib_ckpt_checkpointopen (int fd, void *message) +{ + struct req_lib_ckpt_checkpointopen *req_lib_ckpt_checkpointopen = (struct req_lib_ckpt_checkpointopen *)message; + struct req_exec_ckpt_checkpointopen req_exec_ckpt_checkpointopen; + struct iovec iovecs[2]; + int result; + + log_printf (LOG_LEVEL_DEBUG, "Library request to open checkpoint.\n"); + req_exec_ckpt_checkpointopen.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_checkpointopen.header.size = + sizeof (struct req_exec_ckpt_checkpointopen); + req_exec_ckpt_checkpointopen.header.id = MESSAGE_REQ_EXEC_CKPT_CHECKPOINTOPEN; + + req_exec_ckpt_checkpointopen.source.fd = fd; + req_exec_ckpt_checkpointopen.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + memcpy (&req_exec_ckpt_checkpointopen.req_lib_ckpt_checkpointopen, + req_lib_ckpt_checkpointopen, + sizeof (struct req_lib_ckpt_checkpointopen)); + + iovecs[0].iov_base = &req_exec_ckpt_checkpointopen; + iovecs[0].iov_len = sizeof (req_exec_ckpt_checkpointopen); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_lib_ckpt_checkpointopenasync (int fd, void *message) +{ + return (0); +} + + +static int message_handler_req_lib_ckpt_checkpointunlink (int fd, void *message) +{ + struct req_lib_ckpt_checkpointunlink *req_lib_ckpt_checkpointunlink = (struct req_lib_ckpt_checkpointunlink *)message; + struct req_exec_ckpt_checkpointunlink req_exec_ckpt_checkpointunlink; + struct iovec iovecs[2]; + int result; + + req_exec_ckpt_checkpointunlink.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_checkpointunlink.header.size = + sizeof (struct req_exec_ckpt_checkpointunlink); + req_exec_ckpt_checkpointunlink.header.id = MESSAGE_REQ_EXEC_CKPT_CHECKPOINTUNLINK; + + req_exec_ckpt_checkpointunlink.source.fd = fd; + req_exec_ckpt_checkpointunlink.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + memcpy (&req_exec_ckpt_checkpointunlink.req_lib_ckpt_checkpointunlink, + req_lib_ckpt_checkpointunlink, + sizeof (struct req_lib_ckpt_checkpointunlink)); + + iovecs[0].iov_base = &req_exec_ckpt_checkpointunlink; + iovecs[0].iov_len = sizeof (req_exec_ckpt_checkpointunlink); + + result = gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_lib_ckpt_checkpointretentiondurationset (int fd, void *message) +{ + struct req_lib_ckpt_checkpointretentiondurationset *req_lib_ckpt_checkpointretentiondurationset = (struct req_lib_ckpt_checkpointretentiondurationset *)message; + struct req_exec_ckpt_checkpointretentiondurationset req_exec_ckpt_checkpointretentiondurationset; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "DURATION SET FROM API fd %d\n", fd); + req_exec_ckpt_checkpointretentiondurationset.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_checkpointretentiondurationset.header.id = MESSAGE_REQ_EXEC_CKPT_CHECKPOINTRETENTIONDURATIONSET; + req_exec_ckpt_checkpointretentiondurationset.header.size = sizeof (struct req_exec_ckpt_checkpointretentiondurationset); + memcpy (&req_exec_ckpt_checkpointretentiondurationset.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + req_exec_ckpt_checkpointretentiondurationset.retentionDuration = req_lib_ckpt_checkpointretentiondurationset->retentionDuration; + + iovecs[0].iov_base = &req_exec_ckpt_checkpointretentiondurationset; + iovecs[0].iov_len = sizeof (req_exec_ckpt_checkpointretentiondurationset); + + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + + return (0); +} + +static int message_handler_req_lib_ckpt_activecheckpointset (int fd, void *message) +{ + return (0); +} + +static int message_handler_req_lib_ckpt_checkpointstatusget (int fd, void *message) +{ + struct req_lib_ckpt_checkpointstatusget *req_lib_ckpt_checkpointstatusget = (struct req_lib_ckpt_checkpointstatusget *)message; + struct res_lib_ckpt_checkpointstatusget res_lib_ckpt_checkpointstatusget; + struct saCkptCheckpoint *checkpoint; + int memoryUsed = 0; + int numberOfSections = 0; + struct list_head *checkpointSectionList; + struct saCkptCheckpointSection *checkpointSection; + + req_lib_ckpt_checkpointstatusget = 0; /* The request info isn't used */ + log_printf (LOG_LEVEL_DEBUG, "in status get\n"); + + /* + * Count memory used by checkpoint sections + */ + checkpoint = connections[fd].ais_ci.u.libckpt_ci.checkpoint; + for (checkpointSectionList = checkpoint->checkpointSectionsListHead.next; + checkpointSectionList != &checkpoint->checkpointSectionsListHead; + checkpointSectionList = checkpointSectionList->next) { + + checkpointSection = list_entry (checkpointSectionList, + struct saCkptCheckpointSection, list); + + memoryUsed += checkpointSection->sectionDescriptor.sectionSize; + numberOfSections += 1; + } + + /* + * Build checkpoint status get response + */ + res_lib_ckpt_checkpointstatusget.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_checkpointstatusget.header.size = sizeof (struct res_lib_ckpt_checkpointstatusget); + res_lib_ckpt_checkpointstatusget.header.id = MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSTATUSGET; + + memcpy (&res_lib_ckpt_checkpointstatusget.checkpointStatus.checkpointCreationAttributes, + &checkpoint->checkpointCreationAttributes, + sizeof (SaCkptCheckpointCreationAttributesT)); + res_lib_ckpt_checkpointstatusget.checkpointStatus.numberOfSections = numberOfSections; + res_lib_ckpt_checkpointstatusget.checkpointStatus.memoryUsed = memoryUsed; + + log_printf (LOG_LEVEL_DEBUG, "before sending message\n"); + libais_send_response (fd, &res_lib_ckpt_checkpointstatusget, + sizeof (struct res_lib_ckpt_checkpointstatusget)); + return (0); +} + +static int message_handler_req_lib_ckpt_sectioncreate (int fd, void *message) +{ + struct req_lib_ckpt_sectioncreate *req_lib_ckpt_sectioncreate = (struct req_lib_ckpt_sectioncreate *)message; + struct req_exec_ckpt_sectioncreate req_exec_ckpt_sectioncreate; + struct res_lib_ckpt_sectioncreate res_lib_ckpt_sectioncreate; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "Section create from API fd %d\n", fd); + /* + * Determine if checkpoint is opened in write mode If not, send error to api + */ + if ((connections[fd].ais_ci.u.libckpt_ci.checkpointOpenFlags & SA_CKPT_CHECKPOINT_WRITE) == 0) { + res_lib_ckpt_sectioncreate.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectioncreate.header.size = sizeof (struct res_lib_ckpt_sectioncreate); + res_lib_ckpt_sectioncreate.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONCREATE; + res_lib_ckpt_sectioncreate.error = SA_ERR_ACCESS; + + libais_send_response (fd, &res_lib_ckpt_sectioncreate, + sizeof (struct res_lib_ckpt_sectioncreate)); + return (0); + } + + /* + * checkpoint opened is writeable mode so send message to cluster + */ + req_exec_ckpt_sectioncreate.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_sectioncreate.header.id = MESSAGE_REQ_EXEC_CKPT_SECTIONCREATE; + req_exec_ckpt_sectioncreate.header.size = sizeof (struct req_exec_ckpt_sectioncreate); + + memcpy (&req_exec_ckpt_sectioncreate.req_lib_ckpt_sectioncreate, + req_lib_ckpt_sectioncreate, + sizeof (struct req_lib_ckpt_sectioncreate)); + + memcpy (&req_exec_ckpt_sectioncreate.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + + req_exec_ckpt_sectioncreate.source.fd = fd; + req_exec_ckpt_sectioncreate.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + iovecs[0].iov_base = &req_exec_ckpt_sectioncreate; + iovecs[0].iov_len = sizeof (req_exec_ckpt_sectioncreate); + /* + * Send section name and initial data in message + */ + iovecs[1].iov_base = ((char *)req_lib_ckpt_sectioncreate) + sizeof (struct req_lib_ckpt_sectioncreate); + iovecs[1].iov_len = req_lib_ckpt_sectioncreate->header.size - sizeof (struct req_lib_ckpt_sectioncreate); + +#ifdef DEBUG +printf ("LIBRARY SECTIONCREATE string is %s len is %d\n", iovecs[1].iov_base, iovecs[1].iov_len); +printf ("|\n"); +{ int i; + char *suck = iovecs[1].iov_base; +for (i = 0; i < 14;i++) { + + printf ("%c ", suck[i]); +} +} +printf ("|\n"); +#endif + if (iovecs[1].iov_len > 0) { + log_printf (LOG_LEVEL_DEBUG, "IOV_BASE is %s\n", iovecs[1].iov_base); + gmi_mcast (&aisexec_groupname, iovecs, 2, GMI_PRIO_MED); + } else { + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + } + + return (0); +} + +static int message_handler_req_lib_ckpt_sectiondelete (int fd, void *message) +{ + struct req_lib_ckpt_sectiondelete *req_lib_ckpt_sectiondelete = (struct req_lib_ckpt_sectiondelete *)message; + struct req_exec_ckpt_sectiondelete req_exec_ckpt_sectiondelete; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "section delete from API fd %d\n", fd); + + req_exec_ckpt_sectiondelete.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_sectiondelete.header.id = MESSAGE_REQ_EXEC_CKPT_SECTIONDELETE; + req_exec_ckpt_sectiondelete.header.size = sizeof (struct req_exec_ckpt_sectiondelete); + + memcpy (&req_exec_ckpt_sectiondelete.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + + memcpy (&req_exec_ckpt_sectiondelete.req_lib_ckpt_sectiondelete, + req_lib_ckpt_sectiondelete, + sizeof (struct req_lib_ckpt_sectiondelete)); + + req_exec_ckpt_sectiondelete.source.fd = fd; + req_exec_ckpt_sectiondelete.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + iovecs[0].iov_base = &req_exec_ckpt_sectiondelete; + iovecs[0].iov_len = sizeof (req_exec_ckpt_sectiondelete); + + /* + * Send section name + */ + iovecs[1].iov_base = ((char *)req_lib_ckpt_sectiondelete) + sizeof (struct req_lib_ckpt_sectiondelete); + iovecs[1].iov_len = req_lib_ckpt_sectiondelete->header.size - sizeof (struct req_lib_ckpt_sectiondelete); + + if (iovecs[1].iov_len > 0) { + log_printf (LOG_LEVEL_DEBUG, "IOV_BASE is %s\n", iovecs[1].iov_base); + gmi_mcast (&aisexec_groupname, iovecs, 2, GMI_PRIO_MED); + } else { + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + } + + return (0); +} + +static int message_handler_req_lib_ckpt_sectionexpirationtimeset (int fd, void *message) +{ + struct req_lib_ckpt_sectionexpirationtimeset *req_lib_ckpt_sectionexpirationtimeset = (struct req_lib_ckpt_sectionexpirationtimeset *)message; + struct req_exec_ckpt_sectionexpirationtimeset req_exec_ckpt_sectionexpirationtimeset; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "section expiration time set fd=%d\n", fd); + req_exec_ckpt_sectionexpirationtimeset.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_sectionexpirationtimeset.header.id = MESSAGE_REQ_EXEC_CKPT_SECTIONEXPIRATIONTIMESET; + req_exec_ckpt_sectionexpirationtimeset.header.size = sizeof (struct req_exec_ckpt_sectionexpirationtimeset); + + memcpy (&req_exec_ckpt_sectionexpirationtimeset.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + + memcpy (&req_exec_ckpt_sectionexpirationtimeset.req_lib_ckpt_sectionexpirationtimeset, + req_lib_ckpt_sectionexpirationtimeset, + sizeof (struct req_lib_ckpt_sectionexpirationtimeset)); + + req_exec_ckpt_sectionexpirationtimeset.source.fd = fd; + req_exec_ckpt_sectionexpirationtimeset.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + iovecs[0].iov_base = &req_exec_ckpt_sectionexpirationtimeset; + iovecs[0].iov_len = sizeof (req_exec_ckpt_sectionexpirationtimeset); + + /* + * Send section name + */ + iovecs[1].iov_base = ((char *)req_lib_ckpt_sectionexpirationtimeset) + sizeof (struct req_lib_ckpt_sectionexpirationtimeset); + iovecs[1].iov_len = req_lib_ckpt_sectionexpirationtimeset->header.size - sizeof (struct req_lib_ckpt_sectionexpirationtimeset); + + if (iovecs[1].iov_len > 0) { + log_printf (LOG_LEVEL_DEBUG, "IOV_BASE is %s\n", iovecs[1].iov_base); + gmi_mcast (&aisexec_groupname, iovecs, 2, GMI_PRIO_MED); + } else { + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + } + + return (0); +} + +int write_inv = 0; +static int message_handler_req_lib_ckpt_sectionwrite (int fd, void *message) +{ + struct req_lib_ckpt_sectionwrite *req_lib_ckpt_sectionwrite = (struct req_lib_ckpt_sectionwrite *)message; + struct req_exec_ckpt_sectionwrite req_exec_ckpt_sectionwrite; + struct res_lib_ckpt_sectionwrite res_lib_ckpt_sectionwrite; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "Section write from API fd %d\n", fd); +// UNDO printf ("section write %d\n", write_inv++); + /* + * Determine if checkpoint is opened in write mode If not, send error to api + */ + if ((connections[fd].ais_ci.u.libckpt_ci.checkpointOpenFlags & SA_CKPT_CHECKPOINT_WRITE) == 0) { + res_lib_ckpt_sectionwrite.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionwrite.header.size = sizeof (struct res_lib_ckpt_sectionwrite); + res_lib_ckpt_sectionwrite.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONWRITE; + res_lib_ckpt_sectionwrite.error = SA_ERR_ACCESS; + + libais_send_response (fd, &res_lib_ckpt_sectionwrite, + sizeof (struct res_lib_ckpt_sectionwrite)); + return (0); + } + + /* + * checkpoint opened is writeable mode so send message to cluster + */ + req_exec_ckpt_sectionwrite.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_sectionwrite.header.id = MESSAGE_REQ_EXEC_CKPT_SECTIONWRITE; + req_exec_ckpt_sectionwrite.header.size = sizeof (struct req_exec_ckpt_sectionwrite); + + memcpy (&req_exec_ckpt_sectionwrite.req_lib_ckpt_sectionwrite, + req_lib_ckpt_sectionwrite, + sizeof (struct req_lib_ckpt_sectionwrite)); + + memcpy (&req_exec_ckpt_sectionwrite.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + + req_exec_ckpt_sectionwrite.source.fd = fd; + req_exec_ckpt_sectionwrite.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + iovecs[0].iov_base = &req_exec_ckpt_sectionwrite; + iovecs[0].iov_len = sizeof (req_exec_ckpt_sectionwrite); + /* + * Send section name and data to write in message + */ + iovecs[1].iov_base = ((char *)req_lib_ckpt_sectionwrite) + sizeof (struct req_lib_ckpt_sectionwrite); + iovecs[1].iov_len = req_lib_ckpt_sectionwrite->header.size - sizeof (struct req_lib_ckpt_sectionwrite); + +//printf ("LIB writing checkpoint section is %s\n", ((char *)req_lib_ckpt_sectionwrite) + sizeof (struct req_lib_ckpt_sectionwrite)); + if (iovecs[1].iov_len > 0) { + gmi_mcast (&aisexec_groupname, iovecs, 2, GMI_PRIO_MED); + } else { + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + } + + return (0); +} + +static int message_handler_req_lib_ckpt_sectionoverwrite (int fd, void *message) +{ + struct req_lib_ckpt_sectionoverwrite *req_lib_ckpt_sectionoverwrite = (struct req_lib_ckpt_sectionoverwrite *)message; + struct req_exec_ckpt_sectionoverwrite req_exec_ckpt_sectionoverwrite; + struct res_lib_ckpt_sectionoverwrite res_lib_ckpt_sectionoverwrite; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "Section overwrite from API fd %d\n", fd); + /* + * Determine if checkpoint is opened in write mode If not, send error to api + */ + if ((connections[fd].ais_ci.u.libckpt_ci.checkpointOpenFlags & SA_CKPT_CHECKPOINT_WRITE) == 0) { + res_lib_ckpt_sectionoverwrite.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionoverwrite.header.size = sizeof (struct res_lib_ckpt_sectionoverwrite); + res_lib_ckpt_sectionoverwrite.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONOVERWRITE; + res_lib_ckpt_sectionoverwrite.error = SA_ERR_ACCESS; + + libais_send_response (fd, &res_lib_ckpt_sectionoverwrite, + sizeof (struct res_lib_ckpt_sectionoverwrite)); + return (0); + } + + /* + * checkpoint opened is writeable mode so send message to cluster + */ + req_exec_ckpt_sectionoverwrite.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_sectionoverwrite.header.id = MESSAGE_REQ_EXEC_CKPT_SECTIONOVERWRITE; + req_exec_ckpt_sectionoverwrite.header.size = sizeof (struct req_exec_ckpt_sectionoverwrite); + + memcpy (&req_exec_ckpt_sectionoverwrite.req_lib_ckpt_sectionoverwrite, + req_lib_ckpt_sectionoverwrite, + sizeof (struct req_lib_ckpt_sectionoverwrite)); + + memcpy (&req_exec_ckpt_sectionoverwrite.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + + req_exec_ckpt_sectionoverwrite.source.fd = fd; + req_exec_ckpt_sectionoverwrite.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + iovecs[0].iov_base = &req_exec_ckpt_sectionoverwrite; + iovecs[0].iov_len = sizeof (req_exec_ckpt_sectionoverwrite); + /* + * Send section name and data to overwrite in message + */ + iovecs[1].iov_base = ((char *)req_lib_ckpt_sectionoverwrite) + sizeof (struct req_lib_ckpt_sectionoverwrite); + iovecs[1].iov_len = req_lib_ckpt_sectionoverwrite->header.size - sizeof (struct req_lib_ckpt_sectionoverwrite); + + if (iovecs[1].iov_len > 0) { + gmi_mcast (&aisexec_groupname, iovecs, 2, GMI_PRIO_MED); + } else { + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + } + + return (0); +} + +static int message_handler_req_lib_ckpt_sectionread (int fd, void *message) +{ + struct req_lib_ckpt_sectionread *req_lib_ckpt_sectionread = (struct req_lib_ckpt_sectionread *)message; + struct req_exec_ckpt_sectionread req_exec_ckpt_sectionread; + struct res_lib_ckpt_sectionread res_lib_ckpt_sectionread; + struct iovec iovecs[2]; + + log_printf (LOG_LEVEL_DEBUG, "Section overwrite from API fd %d\n", fd); + /* + * Determine if checkpoint is opened in write mode If not, send error to api + */ + if ((connections[fd].ais_ci.u.libckpt_ci.checkpointOpenFlags & SA_CKPT_CHECKPOINT_READ) == 0) { + res_lib_ckpt_sectionread.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectionread.header.size = sizeof (struct res_lib_ckpt_sectionread); + res_lib_ckpt_sectionread.header.id = MESSAGE_RES_CKPT_CHECKPOINT_SECTIONREAD; + res_lib_ckpt_sectionread.error = SA_ERR_ACCESS; + + libais_send_response (fd, &res_lib_ckpt_sectionread, + sizeof (struct res_lib_ckpt_sectionread)); + return (0); + } + + /* + * checkpoint opened is writeable mode so send message to cluster + */ + req_exec_ckpt_sectionread.header.magic = MESSAGE_MAGIC; + req_exec_ckpt_sectionread.header.id = MESSAGE_REQ_EXEC_CKPT_SECTIONREAD; + req_exec_ckpt_sectionread.header.size = sizeof (struct req_exec_ckpt_sectionread); + + memcpy (&req_exec_ckpt_sectionread.req_lib_ckpt_sectionread, + req_lib_ckpt_sectionread, + sizeof (struct req_lib_ckpt_sectionread)); + + memcpy (&req_exec_ckpt_sectionread.checkpointName, + &connections[fd].ais_ci.u.libckpt_ci.checkpoint->name, + sizeof (SaNameT)); + + req_exec_ckpt_sectionread.source.fd = fd; + req_exec_ckpt_sectionread.source.in_addr.s_addr = this_ip.sin_addr.s_addr; + + iovecs[0].iov_base = &req_exec_ckpt_sectionread; + iovecs[0].iov_len = sizeof (req_exec_ckpt_sectionread); + /* + * Send section name and data to overwrite in message + */ + iovecs[1].iov_base = ((char *)req_lib_ckpt_sectionread) + sizeof (struct req_lib_ckpt_sectionread); + iovecs[1].iov_len = req_lib_ckpt_sectionread->header.size - sizeof (struct req_lib_ckpt_sectionread); + + if (iovecs[1].iov_len > 0) { + gmi_mcast (&aisexec_groupname, iovecs, 2, GMI_PRIO_MED); + } else { + gmi_mcast (&aisexec_groupname, iovecs, 1, GMI_PRIO_MED); + } + + return (0); +} + +static int message_handler_req_lib_ckpt_checkpointsynchronize (int fd, void *message) +{ + return (0); +} + +static int message_handler_req_lib_ckpt_checkpointsyncronizeasync (int fd, void *message) +{ + return (0); +} + +static int message_handler_req_lib_ckpt_sectioniteratorinitialize (int fd, void *message) +{ + struct req_lib_ckpt_sectioniteratorinitialize *req_lib_ckpt_sectioniteratorinitialize = (struct req_lib_ckpt_sectioniteratorinitialize *)message; + struct res_lib_ckpt_sectioniteratorinitialize res_lib_ckpt_sectioniteratorinitialize; + struct saCkptCheckpoint *ckptCheckpoint; + struct saCkptCheckpointSection *ckptCheckpointSection; + struct saCkptSectionIteratorEntry *ckptSectionIteratorEntries; + struct saCkptSectionIterator *ckptSectionIterator; + struct list_head *checkpointSectionList; + int addEntry = 0; + int iteratorEntries = 0; + SaErrorT error = SA_OK; + + log_printf (LOG_LEVEL_DEBUG, "section iterator initialize\n"); + ckptSectionIterator = &connections[fd].ais_ci.u.libckpt_ci.sectionIterator; + + ckptCheckpoint = findCheckpoint (&req_lib_ckpt_sectioniteratorinitialize->checkpointName); + if (ckptCheckpoint == 0) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * Iterate list of checkpoint sections + */ + for (checkpointSectionList = ckptCheckpoint->checkpointSectionsListHead.next; + checkpointSectionList != &ckptCheckpoint->checkpointSectionsListHead; + checkpointSectionList = checkpointSectionList->next) { + + ckptCheckpointSection = list_entry (checkpointSectionList, + struct saCkptCheckpointSection, list); + + addEntry = 1; + + /* + * Item should be added to iterator list + */ + if (addEntry) { + iteratorEntries += 1; + ckptSectionIteratorEntries = + realloc (ckptSectionIterator->sectionIteratorEntries, + sizeof (struct saCkptSectionIteratorEntry) * iteratorEntries); + if (ckptSectionIteratorEntries == 0) { + if (ckptSectionIterator->sectionIteratorEntries) { + free (ckptSectionIterator->sectionIteratorEntries); + } + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + ckptSectionIteratorEntries[iteratorEntries - 1].active = 1; + ckptSectionIteratorEntries[iteratorEntries - 1].checkpointSection = ckptCheckpointSection; + ckptSectionIterator->sectionIteratorEntries = ckptSectionIteratorEntries; + } + } + ckptSectionIterator->iteratorCount = iteratorEntries; + +error_exit: + res_lib_ckpt_sectioniteratorinitialize.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectioniteratorinitialize.header.size = sizeof (struct res_lib_ckpt_sectioniteratorinitialize); + res_lib_ckpt_sectioniteratorinitialize.header.id = MESSAGE_RES_CKPT_SECTIONITERATOR_SECTIONITERATORINITIALIZE; + res_lib_ckpt_sectioniteratorinitialize.error = error; + + libais_send_response (fd, &res_lib_ckpt_sectioniteratorinitialize, + sizeof (struct res_lib_ckpt_sectioniteratorinitialize)); + + return (0); +} + +static int message_handler_req_lib_ckpt_sectioniteratornext (int fd, void *message) +{ + struct req_lib_ckpt_sectioniteratornext *req_lib_ckpt_sectioniteratornext = (struct req_lib_ckpt_sectioniteratornext *)message; + struct res_lib_ckpt_sectioniteratornext res_lib_ckpt_sectioniteratornext; + struct saCkptSectionIterator *ckptSectionIterator; + SaErrorT error = SA_OK; + int sectionIdSize = 0; + int iteratorPos = 0; + + req_lib_ckpt_sectioniteratornext = 0; /* this variable not used */ + + log_printf (LOG_LEVEL_DEBUG, "section iterator next\n"); + ckptSectionIterator = &connections[fd].ais_ci.u.libckpt_ci.sectionIterator; + + /* + * Find active iterator entry + */ + for (;;) { + /* + * No more sections in iterator + */ + if (ckptSectionIterator->iteratorPos + 1 >= ckptSectionIterator->iteratorCount) { + error = SA_ERR_NOT_EXIST; + goto error_exit; + } + + /* + * active iterator entry + */ + if (ckptSectionIterator->sectionIteratorEntries[ckptSectionIterator->iteratorPos].active == 1) { + break; + } + + ckptSectionIterator->iteratorPos += 1; + } + + /* + * Prepare response to API + */ + iteratorPos = ckptSectionIterator->iteratorPos; + + sectionIdSize = ckptSectionIterator->sectionIteratorEntries[iteratorPos].checkpointSection->sectionDescriptor.sectionId.idLen; + + memcpy (&res_lib_ckpt_sectioniteratornext.sectionDescriptor, + &ckptSectionIterator->sectionIteratorEntries[iteratorPos].checkpointSection->sectionDescriptor, + sizeof (SaCkptSectionDescriptorT)); + + /* + * Get to next iterator entry + */ + ckptSectionIterator->iteratorPos += 1; + +error_exit: + res_lib_ckpt_sectioniteratornext.header.magic = MESSAGE_MAGIC; + res_lib_ckpt_sectioniteratornext.header.size = sizeof (struct res_lib_ckpt_sectioniteratornext) + sectionIdSize; + res_lib_ckpt_sectioniteratornext.header.id = MESSAGE_RES_CKPT_SECTIONITERATOR_SECTIONITERATORNEXT; + res_lib_ckpt_sectioniteratornext.error = error; + + libais_send_response (fd, &res_lib_ckpt_sectioniteratornext, + sizeof (struct res_lib_ckpt_sectioniteratornext)); + + libais_send_response (fd, + ckptSectionIterator->sectionIteratorEntries[iteratorPos].checkpointSection->sectionDescriptor.sectionId.id, + sectionIdSize); + return (0); +} diff --git a/exec/ckpt.h b/exec/ckpt.h index e69de29b..82bc47e6 100644 --- a/exec/ckpt.h +++ b/exec/ckpt.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 "../include/ais_types.h" +#include "../include/ais_msg.h" +#include "poll.h" +#include "parse.h" + +#ifndef CKPT_H_DEFINED +#define CKPT_H_DEFINED + +struct saCkptCheckpointSection { + struct list_head list; + SaCkptSectionDescriptorT sectionDescriptor; + void *sectionData; +}; + +struct saCkptCheckpoint { + struct list_head list; + SaNameT name; + SaCkptCheckpointCreationAttributesT checkpointCreationAttributes; + struct list_head checkpointSectionsListHead; + int referenceCount; + int unlinked; +}; + +struct saCkptSectionIteratorEntry { + int active; + struct saCkptCheckpointSection *checkpointSection; +}; + +struct saCkptSectionIterator { + struct list_head list; + struct saCkptSectionIteratorEntry *sectionIteratorEntries; + int iteratorCount; + int iteratorPos; +}; + +struct libckpt_ci { + struct saCkptCheckpoint *checkpoint; + SaCkptCheckpointOpenFlagsT checkpointOpenFlags; + struct saCkptSectionIterator sectionIterator; +}; + +extern struct service_handler ckpt_service_handler; + +extern struct service_handler ckpt_checkpoint_service_handler; + +extern struct service_handler ckpt_sectioniterator_service_handler; + +#endif /* CKPT_H_DEFINED */ diff --git a/exec/clm.c b/exec/clm.c index e69de29b..5ff6f965 100644 --- a/exec/clm.c +++ b/exec/clm.c @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_msg.h" +#include "../include/list.h" +#include "../include/queue.h" +#include "poll.h" +#include "gmi.h" +#include "parse.h" +#include "main.h" +#include "print.h" +#include "mempool.h" +#include "handlers.h" + +SaClmClusterChangesT thisClusterNodeLastChange = SA_CLM_NODE_JOINED; +SaClmClusterNodeT thisClusterNode; + +#define NODE_MAX 16 + +SaClmClusterNodeT clusterNodes[NODE_MAX]; + +int clusterNodeEntries = 0; + +/* + * Service Interfaces required by service_message_handler struct + */ +static int clmExecutiveInitialize (void); + +static int clmConfChg ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries); + +static int message_handler_req_exec_clm_nodejoin (int fd, void *message); + +static int message_handler_req_clm_init (int fd, void *message); + +static int message_handler_req_clm_trackstart (int fd, void *message); + +static int message_handler_req_clm_trackstop (int fd, void *message); + +static int message_handler_req_clm_nodeget (int fd, void *message); + +static int (*clm_libais_handler_fns[]) (int fd, void *) = { + message_handler_req_clm_trackstart, + message_handler_req_clm_trackstop, + message_handler_req_clm_nodeget +}; + +static int (*clm_aisexec_handler_fns[]) (int fd, void *) = { + message_handler_req_exec_clm_nodejoin +}; + +struct service_handler clm_service_handler = { + libais_handler_fns: clm_libais_handler_fns, + libais_handler_fns_count: sizeof (clm_libais_handler_fns) / sizeof (int (*)), + aisexec_handler_fns: clm_aisexec_handler_fns , + aisexec_handler_fns_count: sizeof (clm_aisexec_handler_fns) / sizeof (int (*)), + confchg_fn: clmConfChg, + libais_init_fn: message_handler_req_clm_init, + libais_exit_fn: 0, + aisexec_init_fn: clmExecutiveInitialize +}; + +static int clmExecutiveInitialize (void) +{ + + memset (clusterNodes, 0, sizeof (SaClmClusterNodeT) * NODE_MAX); + + /* + * Build local cluster node data structure + */ + thisClusterNode.nodeId = this_ip.sin_addr.s_addr; + memcpy (&thisClusterNode.nodeAddress.value, &this_ip.sin_addr, sizeof (struct in_addr)); + thisClusterNode.nodeAddress.length = sizeof (struct in_addr); + strcpy (thisClusterNode.nodeName.value, (char *)inet_ntoa (this_ip.sin_addr)); + thisClusterNode.nodeName.length = strlen (thisClusterNode.nodeName.value); + strcpy (thisClusterNode.clusterName.value, "mvlcge"); + thisClusterNode.clusterName.length = strlen ("mvlcge"); + thisClusterNode.member = 1; + { + struct sysinfo s_info; + time_t current_time; + sysinfo (&s_info); + current_time = time (NULL); + /* (currenttime (s) - uptime (s)) * 1 billion (ns) / 1 (s) */ + thisClusterNode.bootTimestamp = ((SaTimeT)(current_time - s_info.uptime)) * 1000000000; + } + +#ifdef DEBUG + printSaClmClusterNodeT ("this cluster node", &thisClusterNode); +#endif + + memcpy (&clusterNodes[0], &thisClusterNode, sizeof (SaClmClusterNodeT)); + clusterNodeEntries = 1; + + return (0); +} + +static void libraryNotificationCurrentState (int fd) +{ + struct res_clm_trackcallback res_clm_trackcallback; + SaClmClusterNotificationT clusterNotification[NODE_MAX]; + int i; + + if ((connections[fd].ais_ci.u.libclm_ci.trackFlags & SA_TRACK_CURRENT) == 0) { + return; + } + /* + * Turn off track current + */ + connections[fd].ais_ci.u.libclm_ci.trackFlags &= ~SA_TRACK_CURRENT; + + /* + * Build notification list + */ + for (i = 0; i < clusterNodeEntries; i++) { + clusterNotification[i].clusterChanges = SA_CLM_NODE_NO_CHANGE; + + memcpy (&clusterNotification[i].clusterNode, &clusterNodes[i], + sizeof (SaClmClusterNodeT)); + } + + /* + * Send track response + */ + res_clm_trackcallback.header.magic = MESSAGE_MAGIC; + res_clm_trackcallback.header.size = sizeof (struct res_clm_trackcallback) + + sizeof (SaClmClusterNotificationT) * i; + res_clm_trackcallback.header.id = MESSAGE_RES_CLM_TRACKCALLBACK; + res_clm_trackcallback.viewNumber = 0; + res_clm_trackcallback.numberOfItems = i; + res_clm_trackcallback.numberOfMembers = i; + res_clm_trackcallback.notificationBufferAddress = + connections[fd].ais_ci.u.libclm_ci.notificationBufferAddress; + libais_send_response (fd, &res_clm_trackcallback, sizeof (struct res_clm_trackcallback)); + libais_send_response (fd, clusterNotification, sizeof (SaClmClusterNotificationT) * i); +} + +static void libraryNotificationJoin (SaClmNodeIdT node) +{ + struct res_clm_trackcallback res_clm_trackcallback; + SaClmClusterNotificationT clusterNotification; + int fd; + int i; + + /* + * Generate notification element + */ + clusterNotification.clusterChanges = SA_CLM_NODE_JOINED; + for (i = 0; i < clusterNodeEntries; i++) { + if (node == clusterNodes[i].nodeId) { + memcpy (&clusterNotification.clusterNode, &clusterNodes[i], + sizeof (SaClmClusterNodeT)); + } + } + + /* + * Send notifications to all listeners + */ + for (fd = 0; fd < connection_entries; fd++) { + if (connections[fd].service == SOCKET_SERVICE_CLM && + connections[fd].active && + connections[fd].ais_ci.u.libclm_ci.trackFlags) { + + res_clm_trackcallback.header.magic = MESSAGE_MAGIC; + res_clm_trackcallback.header.size = sizeof (struct res_clm_trackcallback) + + sizeof (SaClmClusterNotificationT); + res_clm_trackcallback.header.id = MESSAGE_RES_CLM_TRACKCALLBACK; + res_clm_trackcallback.viewNumber = 0; + res_clm_trackcallback.numberOfItems = 1; + res_clm_trackcallback.numberOfMembers = 1; + res_clm_trackcallback.notificationBufferAddress = + connections[fd].ais_ci.u.libclm_ci.notificationBufferAddress; + libais_send_response (fd, &res_clm_trackcallback, sizeof (struct res_clm_trackcallback)); + libais_send_response (fd, &clusterNotification, sizeof (SaClmClusterNotificationT)); + } + } +} + +static void libraryNotificationLeave (SaClmNodeIdT *nodes, int nodes_entries) +{ + struct res_clm_trackcallback res_clm_trackcallback; + SaClmClusterNotificationT clusterNotification[NODE_MAX]; + int fd; + int i, j; + int notifyEntries; + + /* + * Determine notification list + */ + for (notifyEntries = 0, i = 0; i < clusterNodeEntries; i++) { + for (j = 0; j < nodes_entries; j++) { + if (clusterNodes[i].nodeId == nodes[j]) { + memcpy (&clusterNotification[notifyEntries].clusterNode, + &clusterNodes[i], + sizeof (SaClmClusterNodeT)); + clusterNotification[notifyEntries].clusterChanges = SA_CLM_NODE_LEFT; + notifyEntries += 1; + break; + } + } + } + + /* + * Send notifications to all listeners + */ + for (fd = 0; fd < connection_entries; fd++) { + if (connections[fd].service == SOCKET_SERVICE_CLM && + connections[fd].active && + connections[fd].ais_ci.u.libclm_ci.trackFlags) { + + if (notifyEntries) { + res_clm_trackcallback.header.magic = MESSAGE_MAGIC; + res_clm_trackcallback.header.size = sizeof (struct res_clm_trackcallback) + + (notifyEntries * sizeof (SaClmClusterNotificationT)); + res_clm_trackcallback.header.id = MESSAGE_RES_CLM_TRACKCALLBACK; + res_clm_trackcallback.viewNumber = 0; + res_clm_trackcallback.numberOfItems = notifyEntries; + res_clm_trackcallback.numberOfMembers = notifyEntries; + res_clm_trackcallback.notificationBufferAddress = + connections[fd].ais_ci.u.libclm_ci.notificationBufferAddress; + libais_send_response (fd, &res_clm_trackcallback, sizeof (struct res_clm_trackcallback)); + libais_send_response (fd, clusterNotification, sizeof (SaClmClusterNotificationT) * notifyEntries); + } + } + } + + /* + * Remove entries from clusterNodes array + */ + for (i = 0; i < nodes_entries; i++) { + for (j = 0; j < clusterNodeEntries;) { + if (nodes[i] == clusterNodes[j].nodeId) { + clusterNodeEntries -= 1; + memcpy (&clusterNodes[j], &clusterNodes[j + 1], + (clusterNodeEntries - i) * sizeof (SaClmClusterNodeT)); + } else { + /* + * next clusterNode entry + */ + j++; + } + } + } +} + +static int clmNodeJoinSend (void) +{ + struct req_exec_clm_nodejoin req_exec_clm_nodejoin; + struct iovec req_exec_clm_iovec; + int result; + req_exec_clm_nodejoin.header.magic = MESSAGE_MAGIC; + req_exec_clm_nodejoin.header.size = sizeof (struct req_exec_clm_nodejoin); + req_exec_clm_nodejoin.header.id = MESSAGE_REQ_EXEC_CLM_NODEJOIN; +// TODO dont use memcpy, use iovecs !! + memcpy (&req_exec_clm_nodejoin.clusterNode, &thisClusterNode, + sizeof (SaClmClusterNodeT)); + + req_exec_clm_iovec.iov_base = &req_exec_clm_nodejoin; + req_exec_clm_iovec.iov_len = sizeof (req_exec_clm_nodejoin); + + result = gmi_mcast (&aisexec_groupname, &req_exec_clm_iovec, 1, GMI_PRIO_HIGH); + + return (result); +} + +static int clmConfChg ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries) { + + int i; + SaClmNodeIdT nodes[NODE_MAX]; + + log_printf (LOG_LEVEL_NOTICE, "CLM CONFIGURATION CHANGE\n"); + log_printf (LOG_LEVEL_NOTICE, "New Configuration:\n"); + for (i = 0; i < member_list_entries; i++) { + log_printf (LOG_LEVEL_NOTICE, "\t%s\n", inet_ntoa (member_list[i].sin_addr)); + } + log_printf (LOG_LEVEL_NOTICE, "Members Left:\n"); + for (i = 0; i < left_list_entries; i++) { + log_printf (LOG_LEVEL_NOTICE, "\t%s\n", inet_ntoa (left_list[i].sin_addr)); + } + + log_printf (LOG_LEVEL_NOTICE, "Members Joined:\n"); + for (i = 0; i < joined_list_entries; i++) { + log_printf (LOG_LEVEL_NOTICE, "\t%s\n", inet_ntoa (joined_list[i].sin_addr)); + } + + /* + * Send node information to other nodes + */ + if (joined_list_entries) { + clmNodeJoinSend (); + } + for (i = 0; i < left_list_entries; i++) { + nodes[i] = left_list[i].sin_addr.s_addr; + } + + libraryNotificationLeave (nodes, i); + + return (0); +} + +static int message_handler_req_exec_clm_nodejoin (int fd, void *message) +{ + struct req_exec_clm_nodejoin *req_exec_clm_nodejoin = (struct req_exec_clm_nodejoin *)message; + int found; + int i; + + log_printf (LOG_LEVEL_NOTICE, "got nodejoin message %s\n", req_exec_clm_nodejoin->clusterNode.nodeName.value); + + /* + * Determine if nodejoin already received + */ + for (found = 0, i = 0; i < clusterNodeEntries; i++) { + if (memcmp (&clusterNodes[i], &req_exec_clm_nodejoin->clusterNode, + sizeof (SaClmClusterNodeT)) == 0) { + + found = 1; + } + } + + /* + * If not received, add to internal list + */ + if (found == 0) { + memcpy (&clusterNodes[clusterNodeEntries], + &req_exec_clm_nodejoin->clusterNode, + sizeof (SaClmClusterNodeT)); + + clusterNodeEntries += 1; + libraryNotificationJoin (req_exec_clm_nodejoin->clusterNode.nodeId); + } + + return (0); +} + +static int message_handler_req_clm_init (int fd, void *message) +{ + log_printf (LOG_LEVEL_DEBUG, "Got request to initalize cluster membership service.\n"); + connections[fd].service = SOCKET_SERVICE_CLM; + + return (0); +} + +int message_handler_req_clm_trackstart (int fd, void *message) +{ + struct req_clm_trackstart *req_clm_trackstart = (struct req_clm_trackstart *)message; + + + connections[fd].ais_ci.u.libclm_ci.trackFlags = req_clm_trackstart->trackFlags; + connections[fd].ais_ci.u.libclm_ci.notificationBufferAddress = req_clm_trackstart->notificationBufferAddress; + + libraryNotificationCurrentState (fd); + + return (0); +} + +static int message_handler_req_clm_trackstop (int fd, void *message) +{ + connections[fd].ais_ci.u.libclm_ci.trackFlags = 0; + connections[fd].ais_ci.u.libclm_ci.notificationBufferAddress = 0; + + return (0); +} + +static int message_handler_req_clm_nodeget (int fd, void *message) +{ + struct req_clm_nodeget *req_clm_nodeget = (struct req_clm_nodeget *)message; + struct res_clm_nodeget res_clm_nodeget; + SaClmClusterNodeT *clusterNode = 0; + int valid = 0; + int i; + + log_printf (LOG_LEVEL_DEBUG, "nodeget: trying to find node %x\n", (int)req_clm_nodeget->nodeId); + + if (req_clm_nodeget->nodeId == SA_CLM_LOCAL_NODE_ID) { + clusterNode = &clusterNodes[0]; + valid = 1; + } else + for (i = 0; i < clusterNodeEntries; i++) { + if (clusterNodes[i].nodeId == req_clm_nodeget->nodeId) { + log_printf (LOG_LEVEL_DEBUG, "found host that matches one desired in nodeget.\n"); + clusterNode = &clusterNodes[i]; + valid = 1; + break; + } + } + + res_clm_nodeget.header.magic = MESSAGE_MAGIC; + res_clm_nodeget.header.size = sizeof (struct res_clm_nodeget); + res_clm_nodeget.header.id = MESSAGE_RES_CLM_NODEGET; + res_clm_nodeget.invocation = req_clm_nodeget->invocation; + res_clm_nodeget.clusterNodeAddress = req_clm_nodeget->clusterNodeAddress; + res_clm_nodeget.valid = valid; + if (valid) { + memcpy (&res_clm_nodeget.clusterNode, clusterNode, sizeof (SaClmClusterNodeT)); + } + libais_send_response (fd, &res_clm_nodeget, sizeof (struct res_clm_nodeget)); + + return (0); +} diff --git a/exec/clm.h b/exec/clm.h index e69de29b..cb132f23 100644 --- a/exec/clm.h +++ b/exec/clm.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 "../include/ais_types.h" + +#ifndef CLM_H_DEFINED +#define CLM_H_DEFINED + +#include + +struct libclm_ci { + SaUint8T trackFlags; + SaClmClusterNotificationT *notificationBufferAddress; +}; + +extern SaClmClusterNodeT thisClusterNode; + +extern struct service_handler clm_service_handler; + +#endif /* CLM_H_DEFINED */ diff --git a/exec/gmi.c b/exec/gmi.c index e69de29b..c11ed4cd 100644 --- a/exec/gmi.c +++ b/exec/gmi.c @@ -0,0 +1,2861 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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. + */ + +/* + * This code implements the ring protocol specified in Yair Amir's PhD thesis: + * http://www.cs.jhu.edu/~yairamir/phd.ps) (ch4,5). + * + * Some changes have been made to the design to support things like fragmentation, + * multiple I/O queues, and other things. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "poll.h" +#include "gmi.h" +#include "../include/queue.h" +#include "../include/sq.h" +#include "print.h" + +extern struct sockaddr_in this_ip; + +#define LOCALHOST_IP inet_addr("127.0.0.1") +#define QUEUE_PEND_DELV_SIZE_MAX ((MESSAGE_SIZE_MAX / 1472) + 1) * 2 +#define QUEUE_RTR_ITEMS_SIZE_MAX 512 +#define QUEUE_PEND_TRANS_SIZE_MAX ((MESSAGE_SIZE_MAX / 1472) + 1) * 500 +#define MAXIOVS 8 +#define RTR_TOKEN_SIZE_MAX 32 +#define MISSING_MCAST_WINDOW 64 +#define TIMEOUT_STATE_GATHER 300 +#define TIMEOUT_TOKEN 300 +#define TIMEOUT_STATE_COMMIT 300 +#define MAX_MEMBERS 16 +#define HOLE_LIST_MAX MISSING_MCAST_WINDOW +#define PRIORITY_MAX 3 + +int stats_sent = 0; +int stats_recv = 0; +int stats_delv = 0; +int stats_remcasts = 0; +int stats_orf_token = 0; +int stats_form_token = 0; +struct timeval stats_tv_start = { 0, 0 }; + +/* + * Flow control mcasts and remcasts on last and current orf_token + */ +int fcc_remcast_last = 0; +int fcc_mcast_last = 0; +int fcc_mcast_current = 0; +int fcc_remcast_current = 0; + +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_ATTEMPT_JOIN = 2, /* membership join attempt message */ + MESSAGE_TYPE_MEMB_JOIN = 3, /* membership join message */ + MESSAGE_TYPE_MEMB_FORM_TOKEN = 4 /* membership FORM token */ +}; + +/* + * In-order pending transmit queue + */ +struct queue queues_pend_trans[PRIORITY_MAX]; + +/* + * In-order pending delivery queue + */ +struct pend_delv { + struct in_addr ip; + int seqid; + int first_delivery; + struct queue queue; +}; + +struct pend_delv queues_pend_delv[MAX_MEMBERS]; + +/* + * Sorted delivery/retransmit queue + */ +struct sq queue_rtr_items; + +/* + * Multicast address + */ +struct sockaddr_in sockaddr_in_mcast; + +/* + * Multicast file descriptor + */ +int gmi_fd; + +/* + * Received up to and including + */ +int gmi_arut = 0; + +/* + * Delivered up to and including + */ +int gmi_adut = 0; + +int gmi_adut_old = 0; + +int gmi_original_arut = 0; + +int gmi_highest_seq = 0; + +int gmi_highest_seq_old = 0; + +int gmi_barrier_seq = 0; + +int gmi_last_seqid = 0; + +int gmi_fragment = 0; + +int gmi_pend_queue_priority = 0; + +/* + * Timers + */ +poll_timer_handle timer_orf_token_timeout = 0; + +poll_timer_handle timer_form_token_timeout = 0; + +poll_timer_handle timer_memb_state_gather_timeout = 0; + +poll_timer_handle timer_memb_state_commit_timeout = 0; + +poll_timer_handle timer_single_member = 0; + +/* + * Function called when new message received + */ +int (*gmi_recv) (char *group, struct iovec *iovec, int iov_len); + +struct message_header { + int type; + int seqid; +}; + +struct memb_conf_id { + struct in_addr rep; + struct timeval tv; +}; + +struct mcast { + struct message_header header; + char priority; + struct memb_conf_id memb_conf_id; + short packet_number; + short packet_count; + int packet_seq; + struct in_addr source; + struct gmi_groupname groupname; +}; + +struct rtr_item { + struct memb_conf_id conf_id; + int seqid; +}; + +struct orf_token { + struct message_header header; + int group_arut; + struct in_addr addr_arut; + short int fcc; + short int brake; + struct in_addr brake_addr; + struct rtr_item rtr_list[RTR_TOKEN_SIZE_MAX]; + int rtr_list_entries; +}; + +struct conf_desc { + struct memb_conf_id conf_id; + int highest_seq; + int arut; +#ifdef COMPLIE_OUT + int hole_list[HOLE_LIST_MAX]; + int hole_list_entries; +#endif +}; + +struct memb_form_token { + struct message_header header; + struct memb_conf_id conf_id; + struct conf_desc conf_desc_list[MAX_MEMBERS]; /* SHOULD BE MAX_MEMBERS */ + int conf_desc_list_entries; + struct in_addr member_list[MAX_MEMBERS]; + int member_list_entries; + struct in_addr rep_list[MAX_MEMBERS]; + int rep_list_entries; +}; + + +struct memb_attempt_join { + struct message_header header; +}; + +struct memb_join { + struct message_header header; + struct in_addr active_rep_list[MAX_MEMBERS]; + int active_rep_list_entries; + struct in_addr failed_rep_list[MAX_MEMBERS]; + int failed_rep_list_entries; +}; + +struct gmi_pend_trans_item { + struct mcast *mcast; + + struct iovec iovec[MAXIOVS]; + int iov_len; +}; + +struct gmi_pend_delv_item { + struct iovec iovec[MAXIOVS]; + int iov_len; +}; + +struct gmi_rtr_item { + struct iovec iovec[MAXIOVS+2]; /* +2 is for mcast msg + group name TODO is this right */ + int iov_len; +}; + +enum memb_state { + MEMB_STATE_OPERATIONAL, + MEMB_STATE_GATHER, + MEMB_STATE_COMMIT, + MEMB_STATE_FORM, + MEMB_STATE_EVS +}; + +static enum memb_state memb_state = MEMB_STATE_GATHER; + +static struct sockaddr_in memb_list[MAX_MEMBERS]; +static int memb_list_entries = 1; +static int memb_list_entries_confchg = 1; + +struct sockaddr_in memb_next; + +struct in_addr memb_gather_set[MAX_MEMBERS]; +int memb_gather_set_entries = 0; + +struct memb_commit_set { + struct sockaddr_in rep; + struct in_addr join_rep_list[MAX_MEMBERS]; + int join_rep_list_entries; + struct in_addr member_list[MAX_MEMBERS]; + int member_list_entries; +}; + +static struct memb_commit_set memb_commit_set[MAX_MEMBERS]; + +static int memb_commit_set_entries = 0; + +static struct in_addr memb_failed_list[MAX_MEMBERS]; + +static int memb_failed_list_entries = 0; + +static struct sockaddr_in memb_local_sockaddr_in; + +static struct memb_conf_id memb_conf_id; + +static struct memb_conf_id memb_form_token_conf_id; + +static struct memb_join memb_join; + +static struct memb_form_token memb_form_token; + +char iov_buffer[MESSAGE_SIZE_MAX]; + +static struct iovec gmi_iov_recv = { + iov_base: iov_buffer, + iov_len: sizeof (iov_buffer) +}; + +struct message_handlers { + int count; + int (*handler_functions[5]) (struct sockaddr_in *, struct iovec *, int, int); +}; + +poll_handle *gmi_poll_handle; + +void (*gmi_deliver_fn) ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len) = 0; + +void (*gmi_confchg_fn) ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries) = 0; + +/* + * forward decls + */ +static int message_handler_orf_token (struct sockaddr_in *, struct iovec *, int, int); +static int message_handler_mcast (struct sockaddr_in *, struct iovec *, int, int); +static int message_handler_memb_attempt_join (struct sockaddr_in *, struct iovec *, int, int); +static int message_handler_memb_join (struct sockaddr_in *, struct iovec *, int, int); +static int message_handler_memb_form_token (struct sockaddr_in *, struct iovec *, int, int); +static void memb_conf_id_build (struct memb_conf_id *, struct in_addr); +static int recv_handler (poll_handle handle, int fd, int revents, void *data); +static int local_netif_determine (struct sockaddr_in *bindnet, struct sockaddr_in *bound_to); +static int memb_state_gather_enter (void); +static void pending_queues_deliver (void); +static int orf_token_mcast (struct orf_token *orf_token, + int fcc_mcasts_allowed, struct sockaddr_in *system_from); +static void queues_pend_delv_memb_new (void); +static void calculate_group_arut (struct orf_token *orf_token); +static int messages_free (int group_arut); + +struct message_handlers gmi_message_handlers = { + 5, + { + message_handler_orf_token, + message_handler_mcast, + message_handler_memb_attempt_join, + message_handler_memb_join, + message_handler_memb_form_token + } +}; + +/* + * Exported interfaces + */ +int gmi_init ( + struct sockaddr_in *sockaddr_mcast, + struct sockaddr_in *sockaddr_bindnet, + poll_handle *poll_handle, + struct sockaddr_in *bound_to) +{ + int res; + struct ip_mreqn mreqn; + struct sockaddr_in sockaddr_in; + char flag; + int i; + int index; + + memcpy (&sockaddr_in_mcast, sockaddr_mcast, sizeof (struct sockaddr_in)); + + for (i = 0; i < PRIORITY_MAX; i++) { + queue_init (&queues_pend_trans[i], QUEUE_PEND_TRANS_SIZE_MAX, + sizeof (struct gmi_pend_trans_item)); + } + sq_init (&queue_rtr_items, QUEUE_RTR_ITEMS_SIZE_MAX, sizeof (struct gmi_rtr_item), 0); + index = local_netif_determine (sockaddr_bindnet, bound_to); + if (index == -1) { + return (-1); + } + memcpy (&memb_list[0], &memb_local_sockaddr_in, sizeof (struct sockaddr_in)); + memb_conf_id_build (&memb_conf_id, memb_local_sockaddr_in.sin_addr); + memcpy (&memb_form_token_conf_id, &memb_conf_id, sizeof (struct memb_conf_id)); + + /* + * Set local sock addr for new socket + */ + sockaddr_in.sin_family = AF_INET; + sockaddr_in.sin_addr.s_addr = htonl (INADDR_ANY); + sockaddr_in.sin_port = sockaddr_in_mcast.sin_port; + + /* + * Join group membership on socket + */ + mreqn.imr_multiaddr.s_addr = sockaddr_mcast->sin_addr.s_addr; + mreqn.imr_ifindex = index + 1; + + gmi_fd = socket (AF_INET, SOCK_DGRAM, 0); + if (gmi_fd == -1) { + perror ("socket"); + return (-1); + } + + res = bind (gmi_fd, (struct sockaddr *)&sockaddr_in, + sizeof (struct sockaddr_in)); + if (res == -1) { + perror ("bind failed"); + return (-1); + } +#ifdef BROADCAST_CODE_TAKEN_OUT +this code is the broadcast socket option vs multicast socket option + setsockopt (gmi_fd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof (on)); +#endif + res = setsockopt (gmi_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &mreqn, sizeof (mreqn)); + if (res == -1) { + perror ("join multicast group failed"); + return (-1); + } + + flag = 0; + res = setsockopt (gmi_fd, IPPROTO_IP, IP_MULTICAST_LOOP, + &flag, sizeof (flag)); + if (res == -1) { + perror ("turn off loopback"); + return (-1); + } + + gmi_poll_handle = poll_handle; + + poll_dispatch_add (*gmi_poll_handle, gmi_fd, POLLIN, 0, recv_handler); + + memb_state_gather_enter (); + + memset (&memb_next, 0, sizeof (struct sockaddr_in)); + + queues_pend_delv_memb_new (); + + return (0); +} + +int gmi_join ( + struct gmi_groupname *groupname, + void (*deliver_fn) ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len), + void (*confchg_fn) ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries), + gmi_join_handle *handle_out) { + + gmi_deliver_fn = deliver_fn; + gmi_confchg_fn = confchg_fn; + *handle_out = 0; + + return (0); +} + +int local_host_seq_count = 0; + +int gmi_leave ( + gmi_join_handle handle_join); + +static int gmi_pend_trans_item_store ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len, + int priority, + short packet_number, short packet_count) +{ + int i, j; + struct gmi_pend_trans_item gmi_pend_trans_item; + /* + * Store pending item + */ + gmi_pend_trans_item.mcast = malloc (sizeof (struct mcast)); + if (gmi_pend_trans_item.mcast == 0) { + goto error_mcast; + } + + /* + * Set mcast header + */ + gmi_pend_trans_item.mcast->header.type = MESSAGE_TYPE_MCAST; + gmi_pend_trans_item.mcast->priority = priority; + gmi_pend_trans_item.mcast->packet_number = packet_number; + gmi_pend_trans_item.mcast->packet_count = packet_count; + gmi_pend_trans_item.mcast->packet_seq = local_host_seq_count++; + gmi_pend_trans_item.mcast->source.s_addr = this_ip.sin_addr.s_addr; + + memcpy (&gmi_pend_trans_item.mcast->groupname, groupname, + sizeof (struct gmi_groupname)); + + for (i = 0; i < iov_len; i++) { + gmi_pend_trans_item.iovec[i].iov_base = malloc (iovec[i].iov_len); + if (gmi_pend_trans_item.iovec[i].iov_base == 0) { + goto error_iovec; + } + memcpy (gmi_pend_trans_item.iovec[i].iov_base, iovec[i].iov_base, + iovec[i].iov_len); + gmi_pend_trans_item.iovec[i].iov_len = iovec[i].iov_len; + } + gmi_pend_trans_item.iov_len = iov_len; + + log_printf (LOG_LEVEL_DEBUG, "mcasted message added to pending queue\n"); + queue_item_add (&queues_pend_trans[priority], &gmi_pend_trans_item); + + return (0); +error_iovec: + for (j = 0; j < i; j++) { + free (gmi_pend_trans_item.iovec[j].iov_base); + } + return (-1); +error_mcast: + return (0); +} + +/* + * 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 the algorithm + * and reassembled at the receiver. + */ +#define FRAGMENT_SIZE (1500 - sizeof (struct mcast) - 20 - 8) + +static void timer_function_single_member (void *data); + +static void single_member_deliver (void) +{ + struct orf_token orf_token; + + memset (&orf_token, 0, sizeof (struct orf_token)); + orf_token.header.seqid = gmi_arut; + orf_token.header.type = MESSAGE_TYPE_ORF_TOKEN; + orf_token.group_arut = gmi_arut; + orf_token.rtr_list_entries = 0; + orf_token_mcast (&orf_token, 99, &memb_local_sockaddr_in); + calculate_group_arut (&orf_token); + messages_free (gmi_arut); + poll_timer_delete (*gmi_poll_handle, timer_single_member); + timer_form_token_timeout = 0; + poll_timer_add (*gmi_poll_handle, 1, 0, + timer_function_single_member, &timer_single_member); +} + +static void timer_function_single_member (void *data) +{ + single_member_deliver (); +} + +int gmi_mcast ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len, + int priority) +{ + int res; + struct iovec copied_iovec; + struct iovec pending_iovecs[MAXIOVS]; + int pending_iovec_entries = 0; + int iovec_entry = 0; + int total_size; + int packet_size; + int i; + int packet_number = 0; + int packet_count = 0; + + packet_size = FRAGMENT_SIZE; + + log_printf (LOG_LEVEL_DEBUG, "MCASTING MESSAGE\n"); + + /* + * Determine size of total message + */ + total_size = 0; + for (i = 0; i < iov_len; i++) { + total_size += iovec[i].iov_len; + assert (iovec[i].iov_len < MESSAGE_SIZE_MAX); + } + + packet_count = (total_size / packet_size); + + log_printf (LOG_LEVEL_DEBUG, "Message size is %d\n", total_size); + + /* + * Break message up into individual packets and publish them + */ + copied_iovec.iov_base = iovec[0].iov_base; + copied_iovec.iov_len = iovec[0].iov_len; + packet_size = 0; + pending_iovec_entries = 0; + iovec_entry = 0; + do { + if (copied_iovec.iov_len + packet_size > FRAGMENT_SIZE) { + pending_iovecs[pending_iovec_entries].iov_base = copied_iovec.iov_base; + pending_iovecs[pending_iovec_entries].iov_len = FRAGMENT_SIZE - packet_size; + copied_iovec.iov_base += FRAGMENT_SIZE - packet_size; + copied_iovec.iov_len -= FRAGMENT_SIZE - packet_size; + packet_size += pending_iovecs[pending_iovec_entries].iov_len; + } else { + pending_iovecs[pending_iovec_entries].iov_base = copied_iovec.iov_base; + pending_iovecs[pending_iovec_entries].iov_len = copied_iovec.iov_len; + packet_size += copied_iovec.iov_len; + iovec_entry += 1; /* this must be before copied_iovec */ + copied_iovec.iov_base = iovec[iovec_entry].iov_base; + copied_iovec.iov_len = iovec[iovec_entry].iov_len; + } + pending_iovec_entries += 1; + if (packet_size >= FRAGMENT_SIZE || packet_size == total_size) { +#ifdef DEBUG +for (i = 0; i < pending_iovec_entries; i++) { + assert (pending_iovecs[i].iov_len < MESSAGE_SIZE_MAX); + assert (pending_iovecs[i].iov_len >= 0); + printf ("iovecs[%d] %x %d\n", i, pending_iovecs[i].iov_base, pending_iovecs[i].iov_len); +calced_total += pending_iovecs[i].iov_len; +} +printf ("CALCULATED TOTAL is %d\n", calced_total); +#endif + total_size -= packet_size; + assert (total_size >= 0); + res = gmi_pend_trans_item_store (groupname, pending_iovecs, + pending_iovec_entries, priority, packet_number, packet_count); + pending_iovec_entries = 0; + iovec_entry = 0; + packet_size = 0; + packet_number += 1; + } + } while (total_size > 0); + + /* + * The queued messages are sent in orf_token_mcast, not this function + * But if this processor is the only node, it must deliver the messages + * for self-delivery requirements because orf_token_mcast is only called + * on reception of a token + */ + if (memb_list_entries == 1) { + single_member_deliver (); + } + + return (0); +} + +static int local_netif_determine (struct sockaddr_in *bindnet, struct sockaddr_in *bound_to) +{ + struct sockaddr_in *sockaddr_in; + int id_fd; + struct ifconf ifc; + int numreqs = 0; + int res; + int i; + + /* + * Generate list of local interfaces in ifc.ifc_req structure + */ + id_fd = socket (AF_INET, SOCK_DGRAM, 0); + ifc.ifc_buf = 0; + do { + numreqs += 8; + ifc.ifc_len = sizeof (struct ifreq) * numreqs; + ifc.ifc_buf = (void *)realloc(ifc.ifc_buf, ifc.ifc_len); + res = ioctl (id_fd, SIOCGIFCONF, &ifc); + if (res < 0) { + close (id_fd); + return -1; + } + } while (ifc.ifc_len == sizeof (struct ifreq) * numreqs); + + res = -1; + + /* + * Find interface to bind to + */ + for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) { + sockaddr_in = (struct sockaddr_in *)&ifc.ifc_ifcu.ifcu_req[i].ifr_ifru.ifru_addr; + if ((sockaddr_in->sin_addr.s_addr & 0x00ffffff) == (bindnet->sin_addr.s_addr & 0x00ffffff)) { + memb_local_sockaddr_in.sin_addr.s_addr = sockaddr_in->sin_addr.s_addr; + memb_local_sockaddr_in.sin_family = AF_INET; + memb_local_sockaddr_in.sin_port = sockaddr_in_mcast.sin_port; + memcpy (bound_to, &memb_local_sockaddr_in, sizeof (struct sockaddr_in)); + res = i; + break; /* for */ + } + } + free (ifc.ifc_buf); + close (id_fd); + + return (res); +} + +/* + * Misc Management + */ +int in_addr_compare (const void *a, const void *b) { + struct in_addr *in_addr_a = (struct in_addr *)a; + struct in_addr *in_addr_b = (struct in_addr *)b; + + return (in_addr_a->s_addr > in_addr_b->s_addr); +} + +/* + * ORF Token Management + */ +/* + * Recast message to mcast group if it is available + */ +int orf_token_remcast (int seqid) { + struct msghdr msg_mcast; + struct gmi_rtr_item *gmi_rtr_item; + int res; + struct mcast *mcast; + +//printf ("remulticasting %d\n", seqid); + /* + * Get RTR item at seqid, if not available, return + */ + res = sq_item_get (&queue_rtr_items, seqid, (void **)&gmi_rtr_item); + if (res != 0) { + return -1; + } + mcast = gmi_rtr_item->iovec[0].iov_base; + + /* + * Build multicast message + */ + msg_mcast.msg_name = &sockaddr_in_mcast; + msg_mcast.msg_namelen = sizeof (struct sockaddr_in); + msg_mcast.msg_iov = gmi_rtr_item->iovec; + msg_mcast.msg_iovlen = gmi_rtr_item->iov_len; + msg_mcast.msg_control = 0; + msg_mcast.msg_controllen = 0; + msg_mcast.msg_flags = 0; + + /* + * Multicast message + */ + res = sendmsg (gmi_fd, &msg_mcast, MSG_NOSIGNAL | MSG_DONTWAIT); + if (res == -1) { +printf ("error during remulticast %d %d %d\n", seqid, errno, gmi_rtr_item->iov_len); + return (-1); + } + stats_sent += res; + return (0); +} + +int last_group_arut = 0; +int last_released = 0; +int set_arut = -1; + +/* + * Brake output multicasts if the missing window is too large + */ +int gmi_brake; + +static int messages_free (int group_arut) +{ + struct gmi_rtr_item *gmi_rtr_item_p; + int i, j; + int res; + int lesser; + +// TODO printf ("group arut %d last_group-arut %d gmi_dut %d barrier %d\n", group_arut, last_group_arut, gmi_dut, gmi_barrier_seq); + /* + * Determine braking value (when messages + MISSING_MCAST_WINDOW, stop sending messages) + */ + gmi_brake = group_arut; + if (gmi_brake > last_group_arut) { + gmi_brake = last_group_arut; + } + + /* + * Determine low water mark for messages to be freed + */ + lesser = gmi_brake; + if (lesser > gmi_adut) { + lesser = gmi_adut; + } + +//printf ("Freeing lesser %d %d %d\n", lesser, group_arut, last_group_arut); +//printf ("lesser %d gropu arut %d last group arut %d\n", lesser, group_arut, last_group_arut); + + /* + * return early if no messages can be freed + */ +/* + if (last_released + 1 == lesser) { + return (0); + } +*/ + + /* + * Release retransmit list items if group arut indicates they are transmitted + */ + for (i = last_released; i <= lesser; i++) { + res = sq_item_get (&queue_rtr_items, i, (void **)&gmi_rtr_item_p); + if (res == 0) { + for (j = 0; j < gmi_rtr_item_p->iov_len; j++) { + free (gmi_rtr_item_p->iovec[j].iov_base); + gmi_rtr_item_p->iovec[j].iov_base = (void *)0xdeadbeef; + gmi_rtr_item_p->iovec[j].iov_len = i; + } + } + last_released = i + 1; + } + + sq_items_release (&queue_rtr_items, lesser); + log_printf (LOG_LEVEL_DEBUG, "releasing messages up to and including %d\n", lesser); + return (0); +} + +/* + * Multicasts pending messages onto the ring (requires orf_token possession) + */ +static int orf_token_mcast ( + struct orf_token *orf_token, + int fcc_mcasts_allowed, + struct sockaddr_in *system_from) +{ + struct msghdr msg_mcast; + struct gmi_rtr_item gmi_rtr_item; + struct gmi_pend_trans_item *gmi_pend_trans_item = 0; + int res = 0; + int orf_token_seqid; + struct mcast *mcast; + int last_packet = 1; + struct queue *queue_pend_trans; + + /* + * Disallow multicasts unless state is operational + */ + if (memb_state != MEMB_STATE_OPERATIONAL) { + return (0); + } + + /* + * If received a token with a higher sequence number, + * set highest seq so retransmits can happen at end of + * message stream + */ + if (orf_token->header.seqid > gmi_highest_seq) { + gmi_highest_seq = orf_token->header.seqid; + } + + orf_token_seqid = orf_token->header.seqid; + + queue_pend_trans = &queues_pend_trans[gmi_pend_queue_priority]; + + for (fcc_mcast_current = 0; fcc_mcast_current < fcc_mcasts_allowed; fcc_mcast_current++) { + /* + * determine which pending queue to take message + * from if this is not a message fragment + */ + if (gmi_fragment == 0) { + gmi_pend_queue_priority = 0; + do { + queue_pend_trans = &queues_pend_trans[gmi_pend_queue_priority]; + + if (queue_is_empty (queue_pend_trans)) { + gmi_pend_queue_priority++; + } else { + break; /* from do - found first queue with data */ + } + } while (gmi_pend_queue_priority < PRIORITY_MAX); + } + + if (gmi_pend_queue_priority == PRIORITY_MAX) { + break; /* all queues are empty, break from for */ + } +// printf ("selecting pending queue %d\n", gmi_pend_queue_priority); + + gmi_pend_trans_item = (struct gmi_pend_trans_item *)queue_item_get (queue_pend_trans); + /* preincrement required by algo */ + gmi_pend_trans_item->mcast->header.seqid = ++orf_token->header.seqid; +// UNDO printf ("multicasting seqid %d\n", gmi_pend_trans_item->mcast->header.seqid); + + last_packet = (gmi_pend_trans_item->mcast->packet_number == + gmi_pend_trans_item->mcast->packet_count); +//printf ("last packet is %d current mcast %d\n", last_packet, fcc_mcast_current); + + /* + * Build IO vector + */ + gmi_rtr_item.iovec[0].iov_base = gmi_pend_trans_item->mcast; + gmi_rtr_item.iovec[0].iov_len = sizeof (struct mcast); + + mcast = gmi_rtr_item.iovec[0].iov_base; + + /* + * Is this a fragment of a message + */ + if (mcast->packet_number == mcast->packet_count) { + gmi_fragment = 0; + } else { + gmi_fragment = 1; + } + + memcpy (&mcast->memb_conf_id, &memb_form_token_conf_id, + sizeof (struct memb_conf_id)); + + memcpy (&gmi_rtr_item.iovec[1], gmi_pend_trans_item->iovec, + gmi_pend_trans_item->iov_len * sizeof (struct iovec)); + + gmi_rtr_item.iov_len = gmi_pend_trans_item->iov_len + 1; + + assert (gmi_rtr_item.iov_len < 16); + + /* + * Add message to retransmit queue + */ + sq_item_add (&queue_rtr_items, + &gmi_rtr_item, gmi_pend_trans_item->mcast->header.seqid); + + /* + * Delete item from pending queue + */ + queue_item_remove (queue_pend_trans); + + /* + * Build multicast message + */ + msg_mcast.msg_name = &sockaddr_in_mcast; + msg_mcast.msg_namelen = sizeof (struct sockaddr_in); + msg_mcast.msg_iov = gmi_rtr_item.iovec; + msg_mcast.msg_iovlen = gmi_rtr_item.iov_len; + msg_mcast.msg_control = 0; + msg_mcast.msg_controllen = 0; + msg_mcast.msg_flags = 0; + + /* + * Multicast message + */ + res = sendmsg (gmi_fd, &msg_mcast, MSG_NOSIGNAL | MSG_DONTWAIT); + /* + * An error here is recovered by the multicast algorithm + */ + +// TODO stats_sent isn't right below + stats_sent += res; + } + assert (fcc_mcast_current < 100); +#ifdef OUTA + if (fcc_mcast_current > fcc_mcasts_allowed) { + fcc_mcast_current = fcc_mcasts_allowed; + } +#endif + /* + * If messages mcasted, deliver any new messages to pending queues + */ + if (fcc_mcast_current) { + if (gmi_pend_trans_item->mcast->header.seqid > gmi_highest_seq) { + gmi_highest_seq = gmi_pend_trans_item->mcast->header.seqid; + } + pending_queues_deliver (); +//printf ("orf Token seqid is %d group %d\n", orf_token_seqid, orf_token->group_arut); +#ifdef COMPILE_OUT + if (orf_token_seqid == orf_token->group_arut) { +//printf ("previous group arut #1 %d\n", orf_token->group_arut); + orf_token->group_arut = orf_token_seqid + fcc_mcast_current; + orf_token->addr_arut.s_addr = 0; +} +//printf ("reasing group arut to %d\n", orf_token->group_arut); +#endif + } + + return (res); +} + +/* + * 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 void orf_token_rtr ( + struct orf_token *orf_token, + int *fcc_allowed) +{ + int res; + int i, j; + int found; + +#ifdef COMPLE_OUT +printf ("Retransmit List %d\n", orf_token->rtr_list_entries); +for (i = 0; i < orf_token->rtr_list_entries; i++) { + printf ("%d ", orf_token->rtr_list[i].seqid); +} +printf ("\n"); +#endif + + /* + * Retransmit messages on orf_token's RTR list from RTR queue + */ + for (fcc_remcast_current = 0, i = 0; + fcc_remcast_current <= *fcc_allowed && i < orf_token->rtr_list_entries;) { +#ifdef COMPILE_OUT +printf ("%d.%d.%d vs %d.%d.%d\n", + orf_token->rtr_list[i].conf_id.rep.s_addr, + orf_token->rtr_list[i].conf_id.tv.tv_sec, + orf_token->rtr_list[i].conf_id.tv.tv_usec, + memb_form_token_conf_id.rep.s_addr, + memb_form_token_conf_id.tv.tv_sec, + memb_form_token_conf_id.tv.tv_usec); +#endif + /* + * If this retransmit request isn't from this configuration, + * try next rtr entry + */ + if (memcmp (&orf_token->rtr_list[i].conf_id, &memb_form_token_conf_id, + sizeof (struct memb_conf_id)) != 0) { + + i++; + continue; + } + assert (orf_token->rtr_list[i].seqid > 0); + res = orf_token_remcast (orf_token->rtr_list[i].seqid); + if (res == 0) { + orf_token->rtr_list_entries -= 1; + assert (orf_token->rtr_list_entries >= 0); + memmove (&orf_token->rtr_list[i], + &orf_token->rtr_list[i + 1], + sizeof (struct rtr_item) * (orf_token->rtr_list_entries)); + fcc_remcast_current++; + stats_remcasts++; + } else { + i++; +//printf ("couldn't remcast %d\n", i); + } + } + *fcc_allowed = *fcc_allowed - fcc_remcast_current - 1; + +#ifdef COMPILE_OUT +for (i = 0; i < orf_token->rtr_list_entries; i++) { + assert (orf_token->rtr_list[i].seqid != -1); +} +#endif + + /* + * Add messages to retransmit to RTR list + * but only retry if there is room in the retransmit list + */ + for (i = gmi_arut + 1; + orf_token->rtr_list_entries < RTR_TOKEN_SIZE_MAX && + // i <= orf_token->header.seqid; /* TODO this worked previously but not correct for EVS */ + i <= gmi_highest_seq; + i++) { + + res = sq_item_inuse (&queue_rtr_items, i); + if (res == 0) { + found = 0; + for (j = 0; j < orf_token->rtr_list_entries; j++) { + if (i == orf_token->rtr_list[j].seqid) { + found = 1; + } + } + if (found == 0) { + memcpy (&orf_token->rtr_list[orf_token->rtr_list_entries].conf_id, + &memb_form_token_conf_id, sizeof (struct memb_conf_id)); + orf_token->rtr_list[orf_token->rtr_list_entries].seqid = i; + orf_token->rtr_list_entries++; +//printf ("adding to retransmit list %d\n", i); + } + } + } +} + +/* + * Calculate flow control count + */ +static void orf_token_fcc ( + struct orf_token *orf_token) +{ + orf_token->fcc = orf_token->fcc - fcc_mcast_last - fcc_remcast_last + + fcc_mcast_current + fcc_remcast_current; + + fcc_mcast_last = fcc_mcast_current; + fcc_remcast_last = fcc_remcast_current; +} + +static void queues_pend_delv_memb_new (void) +{ + struct pend_delv pend_delv_new[MAX_MEMBERS]; + int item_index = 0; + int i, j; + int found; + + memset (pend_delv_new, 0, sizeof (struct pend_delv) * MAX_MEMBERS); + + /* + * Build new pending list + */ + for (i = 0; i < memb_list_entries_confchg; i++) { + found = 0; + for (j = 0; j < MAX_MEMBERS; j++) { + /* + * If membership item in queues pending delivery list, copy it + */ + if (memb_list[i].sin_addr.s_addr == queues_pend_delv[j].ip.s_addr) { + memcpy (&pend_delv_new[item_index], &queues_pend_delv[j], + sizeof (struct pend_delv)); + item_index += 1; + found = 1; + break; /* for j = */ + } + } + /* + * If membership item not found in pending delivery list, make new entry + */ + if (found == 0) { + queue_init (&pend_delv_new[item_index].queue, QUEUE_PEND_DELV_SIZE_MAX, + sizeof (struct gmi_pend_delv_item)); + pend_delv_new[item_index].seqid = 0; + pend_delv_new[item_index].ip.s_addr = memb_list[i].sin_addr.s_addr; + item_index += 1; + } + } + + /* + * Copy new list into system list + */ + memcpy (queues_pend_delv, pend_delv_new, + sizeof (struct pend_delv) * MAX_MEMBERS); + + for (i = 0; i < memb_list_entries_confchg; i++) { + /* + * If queue not empty, mark it for first delivery + * otherwise reset seqno + */ + if (queue_is_empty (&queues_pend_delv[i].queue) == 0) { + queues_pend_delv[i].first_delivery = 1; + } else { + queues_pend_delv[i].seqid = 0; + } + } +} + +static int orf_token_evs ( + struct orf_token *orf_token, + int starting_group_arut) +{ + int i, j; + struct sockaddr_in trans_memb_list[MAX_MEMBERS]; + struct sockaddr_in left_list[MAX_MEMBERS]; + struct sockaddr_in joined_list[MAX_MEMBERS]; + int trans_memb_list_entries = 0; + int left_list_entries = 0; + int joined_list_entries = 0; + int found; + +//printf ("group arut is %d %d %d %d\n", orf_token->header.seqid, orf_token->group_arut, gmi_arut, gmi_highest_seq); + /* + * We should only execute this function if we are in EVS membership state + */ + if (memb_state != MEMB_STATE_EVS) { + return (0); + } + + /* + * Delete form token timer since the token has been swallowed + */ + poll_timer_delete (*gmi_poll_handle, timer_form_token_timeout); + timer_form_token_timeout = 0; + +printf ("EVS STATE group arut %d gmi arut %d highest %d barrier %d starting group arut %d\n", orf_token->group_arut, gmi_arut, gmi_highest_seq, gmi_barrier_seq, starting_group_arut); + + /* + * This node has reached highest seq, set local arut to barrier + */ + if (gmi_arut == gmi_highest_seq) { +//printf ("setting arut to barrier %d\n", gmi_barrier_seq); + gmi_arut = gmi_barrier_seq; + } + + /* + * Determine when EVS recovery has completed + */ +//printf ("group arut is %d %d %d\n", orf_token->group_arut, gmi_arut, gmi_highest_seq); +// TODO + if (memb_state == MEMB_STATE_EVS && gmi_arut == gmi_barrier_seq && orf_token->group_arut == gmi_barrier_seq) { + log_printf (LOG_LEVEL_NOTICE, "EVS recovery of messages complete, transitioning to operational.\n"); + /* + * EVS recovery complete, reset local variables + */ + gmi_arut = 0; + + gmi_adut_old = gmi_adut; + gmi_adut = 0; + + gmi_highest_seq_old = gmi_highest_seq; + gmi_highest_seq = 0; + last_group_arut = 0; + sq_reinit (&queue_rtr_items, 0); + + memb_failed_list_entries = 0; + + memb_state = MEMB_STATE_OPERATIONAL; + qsort (memb_form_token.member_list, memb_form_token.member_list_entries, + sizeof (struct in_addr), in_addr_compare); + + + /* + * Determine transitional configuration + */ + for (i = 0; i < memb_list_entries_confchg; i++) { + for (found = 0, j = 0; j < memb_form_token.member_list_entries; j++) { + if (memb_list[i].sin_addr.s_addr == memb_form_token.member_list[j].s_addr) { + found = 1; + break; + } + } + if (found == 1) { + trans_memb_list[trans_memb_list_entries].sin_addr.s_addr = memb_list[i].sin_addr.s_addr; + trans_memb_list[trans_memb_list_entries].sin_family = AF_INET; + trans_memb_list[trans_memb_list_entries].sin_port = sockaddr_in_mcast.sin_port; + trans_memb_list_entries += 1; + } + } + + /* + * Determine nodes that left the configuration + */ + for (i = 0; i < memb_list_entries_confchg; i++) { + for (found = 0, j = 0; j < memb_form_token.member_list_entries; j++) { + if (memb_list[i].sin_addr.s_addr == memb_form_token.member_list[j].s_addr) { + found = 1; + break; /* for j = 0 */ + } + } + /* + * Node left membership, add it to list + */ + if (found == 0) { + left_list[left_list_entries].sin_addr.s_addr = memb_list[i].sin_addr.s_addr; + left_list[left_list_entries].sin_family = AF_INET; + left_list[left_list_entries].sin_port = sockaddr_in_mcast.sin_port; + left_list_entries += 1; + } + } + + /* + * MAIN STEP: + * Deliver transitional configuration + */ + if (gmi_confchg_fn && + (trans_memb_list_entries != memb_list_entries || + (memcmp (trans_memb_list, memb_list, sizeof (struct sockaddr_in) * memb_list_entries) != 0))) { + gmi_confchg_fn (trans_memb_list, trans_memb_list_entries, + left_list, left_list_entries, + 0, 0); + } + + + /* + * Determine nodes that joined the configuration + */ + for (i = 0; i < memb_form_token.member_list_entries; i++) { + for (found = 0, j = 0; j < memb_list_entries_confchg; j++) { + if (memb_form_token.member_list[i].s_addr == memb_list[j].sin_addr.s_addr) { + found = 1; + break; /* for j = 0 */ + } + } + + /* + * Node joined membership, add it to list + */ + if (found == 0) { + joined_list[joined_list_entries].sin_addr.s_addr = memb_form_token.member_list[i].s_addr; + joined_list[joined_list_entries].sin_family = AF_INET; + joined_list[joined_list_entries].sin_port = sockaddr_in_mcast.sin_port; + joined_list_entries += 1; + } + } + + /* + * Install the form token's configuration into the local membership + */ + for (i = 0; i < memb_form_token.member_list_entries; i++) { + memb_list[i].sin_addr.s_addr = memb_form_token.member_list[i].s_addr; + memb_list[i].sin_family = AF_INET; + memb_list[i].sin_port = sockaddr_in_mcast.sin_port; + } + + /* + * Install pending delivery queues + */ + memb_list_entries = memb_form_token.member_list_entries; + memb_list_entries_confchg = memb_list_entries; + queues_pend_delv_memb_new (); + + /* + * Install new conf id + */ + memcpy (&memb_conf_id, &memb_form_token.conf_id, + sizeof (struct memb_conf_id)); + memcpy (&memb_form_token_conf_id, &memb_form_token.conf_id, + sizeof (struct memb_conf_id)); + + /* + * Deliver regular configuration + */ + if (gmi_confchg_fn) { + gmi_confchg_fn (memb_list, memb_list_entries, + left_list, 0, + joined_list, joined_list_entries); + } + } + + return (0); +} + +int gwin = 90; +int pwin = 40; + + +static int orf_fcc_allowed (struct orf_token *token) +{ + int allowed; + + if (memb_state != MEMB_STATE_OPERATIONAL) { + return (0); + } + allowed = gwin + pwin - token->fcc; + if (allowed < 0) { + allowed = 0; + } + if (allowed > gwin) { + allowed = gwin; + } + if (allowed > pwin) { + allowed = pwin; + } + return (allowed); +} + +void timer_function_form_token_timeout (void *data) +{ + log_printf (LOG_LEVEL_WARNING, "Token loss in FORM state\n"); + memb_list_entries = 1; + + /* + * Add highest rep to failed list to ensure termination + */ + memb_failed_list[memb_failed_list_entries++].s_addr = + memb_form_token.rep_list[memb_form_token.rep_list_entries].s_addr; + + memb_state_gather_enter (); +} + +void orf_timer_function_token_timeout (void *data) +{ + switch (memb_state) { + case MEMB_STATE_OPERATIONAL: + log_printf (LOG_LEVEL_WARNING, "Token loss in OPERATIONAL.\n"); + memb_conf_id.rep.s_addr = memb_local_sockaddr_in.sin_addr.s_addr; + memb_list_entries = 1; + + memb_state_gather_enter (); + break; + + case MEMB_STATE_GATHER: + case MEMB_STATE_COMMIT: + log_printf (LOG_LEVEL_WARNING, "Token loss in GATHER or COMMIT.\n"); + memb_list_entries = 1; + break; + + case MEMB_STATE_EVS: + log_printf (LOG_LEVEL_WARNING, "Token loss in EVS state\n"); + memb_list_entries = 1; + memb_state_gather_enter (); + break; + + default: + printf ("token loss in form state doesn't make sense here\n"); + break; + } +} + +/* + * Send orf_token to next member (requires orf_token) + */ +static int orf_token_send ( + struct orf_token *orf_token) +{ + struct msghdr msg_orf_token; + struct iovec iovec_orf_token; + int res; + + poll_timer_delete (*gmi_poll_handle, timer_orf_token_timeout); + + poll_timer_add (*gmi_poll_handle, TIMEOUT_TOKEN, 0, + orf_timer_function_token_timeout, &timer_orf_token_timeout); + + iovec_orf_token.iov_base = orf_token; + iovec_orf_token.iov_len = sizeof (struct orf_token); + + msg_orf_token.msg_name = &memb_next; + msg_orf_token.msg_namelen = sizeof (struct sockaddr_in); + msg_orf_token.msg_iov = &iovec_orf_token; + msg_orf_token.msg_iovlen = 1; + msg_orf_token.msg_control = 0; + msg_orf_token.msg_controllen = 0; + msg_orf_token.msg_flags = 0; + +// THIS IS FOR TESTING ERRORS IN THE EVS STATE +//if ((memb_state == MEMB_STATE_EVS) && ((random () % 3) == 0)) { +//log_printf (LOG_LEVEL_DEBUG, "CAUSING TOKEN LOSS AT EVS STATE\n"); +// return (1); +//} + + res = sendmsg (gmi_fd, &msg_orf_token, MSG_NOSIGNAL); + assert (res != -1); + + /* + * res not used here errors are handled by algorithm + */ + gmi_last_seqid = orf_token->header.seqid; + stats_sent += res; + + return (res); +} + +int orf_token_send_initial (void) +{ + struct orf_token orf_token; + int res; + + orf_token.header.seqid = 0; + orf_token.header.type = MESSAGE_TYPE_ORF_TOKEN; + orf_token.group_arut = gmi_highest_seq; + orf_token.addr_arut.s_addr = this_ip.sin_addr.s_addr; + orf_token.fcc = 0; + + orf_token.rtr_list_entries = 0; + memset (orf_token.rtr_list, 0, sizeof (struct rtr_item) * RTR_TOKEN_SIZE_MAX); + + res = orf_token_send (&orf_token); + + return (res); +} + +/* + * Membership Management + */ +static int memb_join_send (void) +{ + struct msghdr msghdr_join; + struct iovec iovec_join; + int res; + + memb_join.header.seqid = 0; + memb_join.header.type = MESSAGE_TYPE_MEMB_JOIN; + /* + * copy current gather list to representatives list + */ + if ((memb_gather_set_entries == memb_join.active_rep_list_entries) && + (memcmp (memb_join.active_rep_list, memb_gather_set, + sizeof (struct in_addr) * memb_gather_set_entries) == 0) && + (memb_failed_list_entries == memb_join.failed_rep_list_entries) && + (memcmp (memb_join.failed_rep_list, memb_failed_list, + sizeof (struct in_addr) * memb_failed_list_entries) == 0)) { + + return (0); + } + + /* + * Copy active reps + */ + memcpy (memb_join.active_rep_list, memb_gather_set, + sizeof (struct in_addr) * memb_gather_set_entries); + memb_join.active_rep_list_entries = memb_gather_set_entries; + + /* + * Copy failed reps + */ + memcpy (memb_join.failed_rep_list, memb_failed_list, + sizeof (struct in_addr) * memb_failed_list_entries); + memb_join.failed_rep_list_entries = memb_failed_list_entries; + + iovec_join.iov_base = &memb_join; + iovec_join.iov_len = sizeof (struct memb_join); + + msghdr_join.msg_name = &sockaddr_in_mcast; + msghdr_join.msg_namelen = sizeof (struct sockaddr_in); + msghdr_join.msg_iov = &iovec_join; + msghdr_join.msg_iovlen = 1; + msghdr_join.msg_control = 0; + msghdr_join.msg_controllen = 0; + msghdr_join.msg_flags = 0; + + res = sendmsg (gmi_fd, &msghdr_join, MSG_NOSIGNAL | MSG_DONTWAIT); + + return (res); +} + +static int memb_state_commit_enter (void); + +/* + * Update gather_set[0].join_reps with list of failed members + */ +void memb_gather_set_update_failed (struct in_addr *list, int list_entries) +{ + int i; + int j; + + /* + * Remove failed members from gather set + */ + for (i = 0; i < list_entries; i++) { + for (j = 0; j < memb_gather_set_entries; j++) { + if (list[i].s_addr == memb_gather_set[j].s_addr) { + memb_gather_set_entries -= 1; + memcpy (&memb_gather_set[j], + &memb_gather_set[j + 1], + memb_gather_set_entries * sizeof (struct in_addr)); + break; /* for j = 0 */ + } + } + } +} + +static void memb_timer_function_state_commit_timeout (void *data) +{ + int i; + int j; + int k; + int found; + int add_to_failed = 1; + struct sockaddr_in left_list[MAX_MEMBERS]; + int left_list_entries = 0; + + memb_failed_list_entries = 0; + + /* + * No entries responded in commit timeout period + */ + if (memb_commit_set_entries == 0) { + /* + * memb_list_entries only set to 0 when token times out, in which case + * send a configuration change because no messages can be recovered in EVS + */ + if (memb_list_entries == 0) { + log_printf (LOG_LEVEL_NOTICE, "I am the only member.\n"); + if (gmi_confchg_fn) { + /* + * Determine nodes that left the configuration + */ + for (i = 0; i < memb_list_entries_confchg; i++) { + if (memb_local_sockaddr_in.sin_addr.s_addr != memb_list[i].sin_addr.s_addr) { + left_list[left_list_entries].sin_addr.s_addr = memb_list[i].sin_addr.s_addr; + left_list[left_list_entries].sin_family = AF_INET; + left_list[left_list_entries].sin_port = sockaddr_in_mcast.sin_port; + left_list_entries += 1; + + } + } + + gmi_confchg_fn (&memb_local_sockaddr_in, 1, + left_list, left_list_entries, + 0, 0); + } + } else { + log_printf (LOG_LEVEL_NOTICE, "No members sent join, keeping old ring and transitioning to operational.\n"); + } + memb_state = MEMB_STATE_OPERATIONAL; + return; + } + /* + * Find all failed members + */ + for (i = 0; i < memb_gather_set_entries; i++) { + add_to_failed = 1; + for (j = 0; j < memb_commit_set_entries; j++) { + /* + * If gather entry not in commit rep list, add to failed + */ + if (memb_gather_set[i].s_addr == memb_commit_set[j].rep.sin_addr.s_addr) { + add_to_failed = 0; + break; /* for found = 0 */ + } + } + /* + * If gather entry not in commit set, add to failed set + */ + for (found = 0, j = 0; j < memb_commit_set_entries; j++) { + for (k = 0; k < memb_commit_set[j].join_rep_list_entries; k++) { + if (memb_gather_set[i].s_addr == memb_commit_set[j].join_rep_list[k].s_addr) { + found = 1; + break; + } + } + if (found == 0) { + add_to_failed = 1; + break; + } + } + + /* + * If local address, item found + */ + if (memb_gather_set[i].s_addr == memb_local_sockaddr_in.sin_addr.s_addr) { + add_to_failed = 0; + } + + if (add_to_failed == 1) { + memb_failed_list[memb_failed_list_entries++].s_addr = + memb_gather_set[i].s_addr; + } + } + + memb_gather_set_update_failed (memb_failed_list, memb_failed_list_entries); + + memb_state_commit_enter (); +} + +static int memb_state_commit_enter (void) +{ + int res; + + memb_state = MEMB_STATE_COMMIT; + memb_commit_set_entries = 0; + res = memb_join_send(); + + poll_timer_delete (*gmi_poll_handle, timer_memb_state_gather_timeout); + + timer_memb_state_gather_timeout = 0; + + poll_timer_add (*gmi_poll_handle, TIMEOUT_STATE_COMMIT, 0, + memb_timer_function_state_commit_timeout, &timer_memb_state_commit_timeout); + + return (res); +} + +static void memb_timer_function_state_gather (void *data) +{ + int i; + /* + * GATHER period expired, sort gather sets and send JOIN + */ + memb_state_commit_enter (); + log_printf (LOG_LEVEL_DEBUG, "GATHER timeout:\n"); + for (i = 0; i < memb_gather_set_entries; i++) { + log_printf (LOG_LEVEL_DEBUG, "host %d attempted to join %s\n", i, inet_ntoa (memb_gather_set[i])); + } +} + +static void memb_print_commit_set (void) +{ + int i, j; + + log_printf (LOG_LEVEL_DEBUG, "Gather list\n"); + for (i = 0; i < memb_gather_set_entries; i++) { + log_printf (LOG_LEVEL_DEBUG, "\tmember %d %s\n", i, inet_ntoa (memb_gather_set[i])); + } + for (i = 0; i < memb_commit_set_entries; i++) { + log_printf (LOG_LEVEL_DEBUG, "Join from rep %d %s\n", i, inet_ntoa (memb_commit_set[i].rep.sin_addr)); + for (j = 0; j < memb_commit_set[i].join_rep_list_entries; j++) { + log_printf (LOG_LEVEL_DEBUG, "\tmember %d %s\n", j, inet_ntoa (memb_commit_set[i].join_rep_list[j])); + } + } +} + +/* + * Determine if the commit phase has reached consensus + */ +static int memb_state_consensus_commit (void) +{ + int found; + int res; + int i, j; + + /* + * Determine consensus + */ + + /* + * If all commit sets don't match gather set, no consensus + */ + for (i = 0; i < memb_commit_set_entries; i++) { + /* + * If not same number of entries, no consensus + */ + res = memb_gather_set_entries - memb_commit_set[i].join_rep_list_entries; + if (res != 0) { + return (0); /* no consensus */ + } + + /* + * If entries dont match, no consensus + */ + res = memcmp (memb_gather_set, memb_commit_set[i].join_rep_list, + memb_gather_set_entries * sizeof (struct in_addr)); + + if (res != 0) { + return (0); /* no consensus */ + } + } + + /* + * If all reps from gather set represented in commit set, consensus + */ + for (i = 0; i < memb_gather_set_entries; i++) { + found = 0; + for (j = 0; j < memb_commit_set_entries; j++) { + if (memb_gather_set[i].s_addr == memb_local_sockaddr_in.sin_addr.s_addr) { + found = 1; + break; + } + if (memb_gather_set[i].s_addr == memb_commit_set[j].rep.sin_addr.s_addr) { + found = 1; + break; + } + } + + if (found == 0) { + return (0); /* no consensus, rep not found from gather set */ + } + } + + return (1); /* got consensus! */ +} + +/* + * Union commit_set_entry into gather set + */ +static void memb_state_commit_union (int commit_set_entry) +{ +int found; +int i, j; + + for (i = 0; i < memb_commit_set[commit_set_entry].join_rep_list_entries; i++) { + for (found = 0, j = 0; j < memb_gather_set_entries; j++) { + if (memb_commit_set[commit_set_entry].join_rep_list[i].s_addr == + memb_gather_set[j].s_addr) { + found = 1; + break; + } + } + + if (found == 0) { + memb_gather_set[memb_gather_set_entries++].s_addr = + memb_commit_set[commit_set_entry].join_rep_list[i].s_addr; + /* + * Sort gather set + */ + qsort (memb_gather_set, memb_gather_set_entries, + sizeof (struct in_addr), in_addr_compare); + } + } +} + +static void memb_conf_id_build ( + struct memb_conf_id *memb_conf_id, + struct in_addr memb_local_rep) +{ + gettimeofday (&memb_conf_id->tv, NULL); + memb_conf_id->rep.s_addr = memb_local_rep.s_addr; +} + +static void memb_form_token_update_highest_seq ( + struct memb_form_token *form_token) +{ + struct conf_desc *conf_desc; + int entry; + int found = 0; + + for (entry = 0; entry < form_token->conf_desc_list_entries; entry++) { + if (memcmp (&form_token->conf_desc_list[entry].conf_id, + &memb_form_token_conf_id, sizeof (struct memb_conf_id)) == 0) { + + found = 1; + break; + } + } + conf_desc = &form_token->conf_desc_list[entry]; + if (found && gmi_highest_seq < conf_desc->highest_seq) { + gmi_highest_seq = conf_desc->highest_seq; + } +} + +static void memb_form_token_conf_desc_build ( + struct memb_form_token *form_token) +{ + struct conf_desc *conf_desc; + int found = 0; + int entry = 0; + + /* + * Determine if local configuration id is already present in form token + */ + for (entry = 0; entry < form_token->conf_desc_list_entries; entry++) { + if (memcmp (&form_token->conf_desc_list[entry].conf_id, + &memb_form_token_conf_id, sizeof (struct memb_conf_id)) == 0) { + + found = 1; + break; + } + } + conf_desc = &form_token->conf_desc_list[entry]; + + if (found == 0) { + /* + * Item not present, add item + */ + conf_desc->highest_seq = gmi_highest_seq; + conf_desc->arut = gmi_arut; +// TODO holes not currently implemented conf_desc->hole_list_entries = 0; + memcpy (&conf_desc->conf_id, + &memb_form_token_conf_id, sizeof (struct memb_conf_id)); + + form_token->conf_desc_list_entries += 1; + } else { + /* + * Item already present, update arut, highest seq + */ + if (conf_desc->arut > gmi_arut) { + conf_desc->arut = gmi_arut; + } + if (gmi_highest_seq > conf_desc->highest_seq) { + conf_desc->highest_seq = gmi_highest_seq; + } + } + +#ifdef COMPILE_OUT + /* + * Build conf_desc->hole_list + */ +printf ("conf desc build %d %d\n", gmi_arut, gmi_highest_seq); + conf_desc->hole_list_entries = 0; + for (i = gmi_arut; i < gmi_highest_seq; i++) { + assert (conf_desc->hole_list_entries < HOLE_LIST_MAX); + res = sq_item_get (&queue_rtr_items, i, (void **)&gmi_rtr_item_p); + if (res == 0) { + /* + * If item present, delete from hole list if it exists + */ + for (j = 0; j < conf_desc->hole_list_entries; j++) { + if (conf_desc->hole_list[j] == i) { + memmove (&conf_desc->hole_list[j], &conf_desc->hole_list[j + 1], + sizeof (int) * (conf_desc->hole_list_entries - j - 1)); + conf_desc->hole_list_entries -= 1; +printf ("reducing setting desc entries to %d\n", conf_desc->hole_list_entries); + break; /* from for (j = ... ) */ + } + } + } else { + /* + * If item not present, add to hole list + */ + conf_desc->hole_list[conf_desc->hole_list_entries] = i; + conf_desc->hole_list_entries += 1; +printf ("increasing setting desc entries to %d %d\n", conf_desc->hole_list_entries, i); + } + } +printf ("Conf desc build done\n"); +#endif +} + +static int memb_form_token_send ( + struct memb_form_token *form_token) +{ + struct msghdr msg_form_token; + struct iovec iovec_form_token; + int res; + + /* + * Build message for sendmsg + */ + iovec_form_token.iov_base = form_token; + iovec_form_token.iov_len = sizeof (struct memb_form_token); + + msg_form_token.msg_name = &memb_next; + msg_form_token.msg_namelen = sizeof (struct sockaddr_in); + msg_form_token.msg_iov = &iovec_form_token; + msg_form_token.msg_iovlen = 1; + msg_form_token.msg_control = 0; + msg_form_token.msg_controllen = 0; + msg_form_token.msg_flags = 0; + + res = sendmsg (gmi_fd, &msg_form_token, MSG_NOSIGNAL | MSG_DONTWAIT); + + /* + * res not used here, because orf token errors are handled by algorithm + */ + stats_sent += res; + + poll_timer_delete (*gmi_poll_handle, timer_orf_token_timeout); + timer_orf_token_timeout = 0; + + poll_timer_delete (*gmi_poll_handle, timer_form_token_timeout); + + poll_timer_add (*gmi_poll_handle, TIMEOUT_TOKEN, 0, + timer_function_form_token_timeout, &timer_form_token_timeout); + + return (res); +} + +int memb_form_token_send_initial (void) +{ + struct memb_form_token form_token; + int res; + + memset (&form_token, 0x00, sizeof (struct memb_form_token)); + memb_state = MEMB_STATE_FORM; + + /* + * Build form token + */ + form_token.header.type = MESSAGE_TYPE_MEMB_FORM_TOKEN; + memcpy (form_token.rep_list, + memb_gather_set, + memb_gather_set_entries * sizeof (struct in_addr)); + form_token.rep_list_entries = memb_gather_set_entries; + + /* + * Add local member to entry + */ + form_token.member_list[0].s_addr = + memb_local_sockaddr_in.sin_addr.s_addr; + form_token.member_list_entries = 1; + + memb_conf_id_build (&form_token.conf_id, memb_local_sockaddr_in.sin_addr); + + form_token.conf_desc_list_entries = 0; + memb_form_token_conf_desc_build (&form_token); + + /* + * Send FORM to next member, or if no members in this configuration + * to next representative + */ + + if (memb_list_entries <= 1) { + memb_next.sin_addr.s_addr = memb_gather_set[1].s_addr; + } + +// TODO assertion here about the 1 value + memb_next.sin_family = AF_INET; + memb_next.sin_port = sockaddr_in_mcast.sin_port; + + res = memb_form_token_send (&form_token); + + return (res); +} + +void print_stats (void) +{ + struct timeval tv_end; + gettimeofday (&tv_end, NULL); + + log_printf (LOG_LEVEL_NOTICE, "Bytes recv %d\n", stats_recv); + log_printf (LOG_LEVEL_NOTICE, "Bytes sent %d\n", stats_sent); + log_printf (LOG_LEVEL_NOTICE, "Messages delivered %d\n", stats_delv); + log_printf (LOG_LEVEL_NOTICE, "Re-Mcasts %d\n", stats_remcasts); + log_printf (LOG_LEVEL_NOTICE, "Tokens process %d\n", stats_orf_token); +} + +/* + * Authenticates message using nonce, mac, and message body + */ +static int gmi_msg_auth (struct iovec *iovec, int iov_len) +{ + return (0); +} + + +int last_lowered = 1; + +static void calculate_group_arut (struct orf_token *orf_token) +{ +//printf ("group arut %d local arut %d gmi_gmi_highest seq %d\n", orf_token->group_arut, gmi_arut, gmi_highest_seq); +//printf ("last %d group arut %d last arut %d arut %d\n", last_lowered, orf_token->group_arut, last_group_arut, gmi_arut); + + /* + * increase the group arut if we got back the same group + * because everyone has these messages + */ + messages_free (orf_token->group_arut); + if (orf_token->addr_arut.s_addr == this_ip.sin_addr.s_addr) { + orf_token->group_arut = gmi_arut; + } + + if (gmi_arut < orf_token->group_arut) { + orf_token->group_arut = gmi_arut; + orf_token->addr_arut.s_addr = this_ip.sin_addr.s_addr; + } + last_group_arut = orf_token->group_arut; +} + +/* + * Message Handlers + */ + +/* + * message handler called when TOKEN message type received + */ +static int message_handler_orf_token ( + struct sockaddr_in *system_from, + struct iovec *iovec, + int iov_len, + int bytes_received) +{ + struct orf_token *orf_token; + int transmits_allowed; + int starting_group_arut; + + orf_token = iovec[0].iov_base; + +#ifdef PRINT_STATS + if (orf_token->header.seqid > 10000) { + print_stats (); + } +#endif + + if (memb_state == MEMB_STATE_FORM) { + log_printf (LOG_LEVEL_NOTICE, "swallowing ORF token %d.\n", stats_orf_token); + poll_timer_delete (*gmi_poll_handle, timer_orf_token_timeout); + timer_orf_token_timeout = 0; + return (0); + } + +//printf ("Got orf token from %s\n", inet_ntoa (system_from->sin_addr)); + starting_group_arut = orf_token->group_arut; + stats_orf_token++; + + transmits_allowed = orf_fcc_allowed (orf_token); + +//printf ("retransmit allowed %d\n", transmits_allowed); + /* + * Retransmit failed messages and request retransmissions + */ + + orf_token_rtr (orf_token, &transmits_allowed); +//printf ("multicasts allowed %d\n", transmits_allowed); + + /* + * TODO Ok this is ugly and I dont like it. + * + * Flow control to limit number of missing multicast messages + * on lossy switches, this could cause a large window between + * what is delivered locally and what is delivered remotely. + * This window could cause the hole list of the form token to + * be overrun or cause the form token to be large. + */ + + if ((gmi_brake + MISSING_MCAST_WINDOW) < orf_token->header.seqid) { + transmits_allowed = 0; + } + + /* + * Set the group arut and free any messages that can be freed + */ + if (memb_state != MEMB_STATE_EVS) { + calculate_group_arut (orf_token); + } + + /* + * Multicast queued messages + */ + orf_token_mcast (orf_token, transmits_allowed, system_from); + + /* + * Calculate flow control count + */ + orf_token_fcc (orf_token); + + /* + * Deliver membership and messages required by EVS + */ + orf_token_evs (orf_token, starting_group_arut); + + if (memb_state == MEMB_STATE_EVS) { + calculate_group_arut (orf_token); + } + + /* + * Transmit orf_token to next member + */ + orf_token_send (orf_token); + + return (0); +} + +static int memb_state_gather_enter (void) { + struct msghdr msghdr_attempt_join; + struct iovec iovec_attempt_join; + struct memb_attempt_join memb_attempt_join; + int res = 0; + + log_printf (LOG_LEVEL_NOTICE, "entering GATHER state.\n"); + memb_state = MEMB_STATE_GATHER; + + /* + * Join message starts with no entries + */ + memb_join.active_rep_list_entries = 0; + memb_join.failed_rep_list_entries = 0; + + /* + * Copy local host info + */ + memb_gather_set[0].s_addr = memb_local_sockaddr_in.sin_addr.s_addr; + memb_gather_set_entries = 1; + + /* + * If this node is the representative, send attempt join + */ + if (memb_local_sockaddr_in.sin_addr.s_addr == memb_conf_id.rep.s_addr) { + log_printf (LOG_LEVEL_NOTICE, "SENDING attempt join because this node is ring rep.\n"); + memb_attempt_join.header.seqid = 0; + memb_attempt_join.header.type = MESSAGE_TYPE_MEMB_ATTEMPT_JOIN; + + iovec_attempt_join.iov_base = &memb_attempt_join; + iovec_attempt_join.iov_len = sizeof (struct memb_attempt_join); + + msghdr_attempt_join.msg_name = &sockaddr_in_mcast; + msghdr_attempt_join.msg_namelen = sizeof (struct sockaddr_in); + msghdr_attempt_join.msg_iov = &iovec_attempt_join; + msghdr_attempt_join.msg_iovlen = 1; + msghdr_attempt_join.msg_control = 0; + msghdr_attempt_join.msg_controllen = 0; + msghdr_attempt_join.msg_flags = 0; + + res = sendmsg (gmi_fd, &msghdr_attempt_join, MSG_NOSIGNAL | MSG_DONTWAIT); + /* + * res not checked here, there is nothing that can be done + * instead rely on the algorithm to recover from faults + */ + } + + poll_timer_delete (*gmi_poll_handle, timer_memb_state_gather_timeout); + + poll_timer_add (*gmi_poll_handle, TIMEOUT_STATE_GATHER, 0, + memb_timer_function_state_gather, &timer_memb_state_gather_timeout); + + return (res); +} + +struct pend_delv *pend_delv_next_delivery_find (void) +{ + struct pend_delv *pend_delv = 0; + int i; + + /* + * Find first_delivery queue that is not mepty + * this sets the first pend_delv + */ + for (i = 0; i < memb_list_entries_confchg; i++) { + if (queues_pend_delv[i].first_delivery && + queue_is_empty (&queues_pend_delv[i].queue) == 0) { + + pend_delv = &queues_pend_delv[i]; +// printf ("Selecting first queue %s\n", inet_ntoa (pend_delv->ip)); + break; + } + } + + /* + * Search remaining pend_delv for first deliveries with + * smaller sequence numbers + */ + for (++i; i < memb_list_entries_confchg; i++) { + assert (pend_delv); + if (queues_pend_delv[i].first_delivery && + (queue_is_empty (&queues_pend_delv[i].queue) == 0) && + (queues_pend_delv[i].seqid < pend_delv->seqid)) { + + pend_delv = &queues_pend_delv[i]; +// printf ("Selecting first queue %s\n", inet_ntoa (pend_delv->ip)); + } + } + + /* + * Found first_delivery queue that wasn't empty, return it + */ + if (pend_delv) { + return (pend_delv); + } + /* + * No first delivery queues, repeat same + * process looking for any queue + */ + for (i = 0; i < memb_list_entries_confchg; i++) { + if (queue_is_empty (&queues_pend_delv[i].queue) == 0) { + pend_delv = &queues_pend_delv[i]; + break; + } + } + + /* + * Find lowest sequence number queue + */ + for (++i; i < memb_list_entries_confchg; i++) { + assert (pend_delv); + if ((queue_is_empty (&queues_pend_delv[i].queue) == 0) && + (queues_pend_delv[i].seqid < pend_delv->seqid)) { + pend_delv = &queues_pend_delv[i]; + } + } + + return (pend_delv); +} + +static int user_deliver () +{ + struct gmi_pend_delv_item *pend_delv_item; + int i = 0; + int res = 0; + struct iovec iovec_delv[256]; + int iov_len_delv = 0; + struct mcast *mcast = 0; + int messages_delivered = 0; + struct pend_delv *pend_delv; + int retval = 0; + + /* + * Find pend_delv with lowest sequence number. This pend_delv is + * the queue that should be delivered from next + */ + pend_delv = pend_delv_next_delivery_find (); +//printf ("Delivering from queue %s\n", inet_ntoa (pend_delv->ip)); + + /* + * If a message was not assembled on the queue with the lowest + * sequence number, return since there is no reason to attempt assembly. + */ + memset (iovec_delv, 0, sizeof (iovec_delv)); + queue_item_iterator_init (&pend_delv->queue); + assert (queue_is_empty (&pend_delv->queue) == 0); +//printf ("Starting a packet assembly\n"); + do { + pend_delv_item = queue_item_iterator_get (&pend_delv->queue); + mcast = pend_delv_item->iovec[0].iov_base; + + assert (pend_delv_item); + assert (pend_delv_item->iovec[0].iov_len < MESSAGE_SIZE_MAX); + assert (pend_delv_item->iovec[0].iov_len != 0); + assert (pend_delv_item->iovec[0].iov_base != 0); + assert (mcast != (struct mcast *)0xdeadbeef); + assert (pend_delv->ip.s_addr == mcast->source.s_addr); + + messages_delivered += 1; + + /* + * Assemble io vector + */ + if (pend_delv_item->iovec[0].iov_len == sizeof (struct mcast)) { + /* + * Copy iovec from second iovec if this is self-delivered + */ + memcpy (&iovec_delv[iov_len_delv], + &pend_delv_item->iovec[1], + sizeof (struct iovec) * pend_delv_item->iov_len - 1); + iov_len_delv += pend_delv_item->iov_len - 1; + } else { + /* + * Copy iovec from first iovec if this is an external message + */ + iovec_delv[iov_len_delv].iov_base = + pend_delv_item->iovec[0].iov_base + sizeof (struct mcast); + iovec_delv[iov_len_delv].iov_len = + pend_delv_item->iovec[0].iov_len - sizeof (struct mcast); + assert (iovec_delv[iov_len_delv].iov_len < MESSAGE_SIZE_MAX); + iov_len_delv += 1; + if (pend_delv_item->iov_len > 1) { + memcpy (&iovec_delv[iov_len_delv], + &pend_delv_item->iovec[1], + sizeof (struct iovec) * pend_delv_item->iov_len - 1); + iov_len_delv += pend_delv_item->iov_len - 1; + } + } + + assert (iov_len_delv < 256); + assert (iov_len_delv > 0); + +//printf ("Assembling from packet %d of %d of total %d\n", +// mcast->packet_number, mcast->packet_count, mcast->packet_seq); + /* + * Deliver message if this is the last packet + */ + if (mcast->packet_number == mcast->packet_count) { + log_printf (LOG_LEVEL_DEBUG, "Last packet, delivering iovec %d entries seq %d\n", + iov_len_delv, i); + + gmi_deliver_fn ( + &mcast->groupname, + iovec_delv, + iov_len_delv); + + /* + * On the first message delivery: + * Free items in the pending queue up to the barrier message + * set gmi_adut to rut so that message_free may free any messages. + */ + if (pend_delv->first_delivery) { +// printf ("releasing all messages up to %d\n", gmi_adut); +// TODO actually release the messages from the previous configuration +// TODO without a fix here, those messages are leaked + } + + /* + * Because of the ordering guarantees, we are guaranteed that + * pend_delv->seqid on every invocation of user_deliver shall + * increase (or reset to zero). This allows us to set the + * low water mark (gmi_adut) for freeing of messages to atleast + * the beginning of this message. + */ + gmi_adut = pend_delv->seqid; + + /* + * Determine if there are more messages on this queue + */ + res = queue_item_iterator_next (&pend_delv->queue); + if (res == 0) { + /* + * More items to deliver set queues seqid head so + * correct pending queue can be selected next time + */ + pend_delv_item = queue_item_iterator_get (&pend_delv->queue); + mcast = pend_delv_item->iovec[0].iov_base; + pend_delv->seqid = mcast->header.seqid; + for (i = 0; i < messages_delivered; i++) { + queue_item_remove (&pend_delv->queue); + } + } else { + /* + * No more items to deliver + */ + pend_delv->seqid = 0; + queue_reinit (&pend_delv->queue); + } + + retval = 1; + break; /* From do loop */ + } + + res = queue_item_iterator_next (&pend_delv->queue); + } while (res == 0); + return (retval); +} + +struct pend_delv *pend_delv_find (struct in_addr source) +{ + struct pend_delv *pend_delv = 0; + int i; + + for (i = 0; i < memb_list_entries_confchg; i++) { + if (source.s_addr == queues_pend_delv[i].ip.s_addr) { + pend_delv = &queues_pend_delv[i]; + break; + } + } + + return (pend_delv); +} + +static int delivery_outstanding = 0; + +static void pending_queues_deliver (void) +{ + struct gmi_rtr_item *gmi_rtr_item_p; + int i; + int res; + struct mcast *mcast; + struct gmi_pend_delv_item pend_delv_item; + struct pend_delv *pend_delv; + int delivered; + +//printf ("Delivering messages to pending queues\n"); + /* + * Deliver messages in order from rtr queue to pending delivery queue + */ + for (i = gmi_arut + 1; i <= gmi_highest_seq; i++) { + res = sq_item_get (&queue_rtr_items, i, (void **)&gmi_rtr_item_p); + /* + * If hole, stop assembly + */ + if (res != 0) { + break; + } + assert (gmi_rtr_item_p->iovec[0].iov_len < MESSAGE_SIZE_MAX); + mcast = gmi_rtr_item_p->iovec[0].iov_base; + if (mcast == (struct mcast *)0xdeadbeef) { + printf ("seqid %d\n", gmi_rtr_item_p->iovec[0].iov_len); + } + assert (mcast != (struct mcast *)0xdeadbeef); + + /* + * Message found + */ + log_printf (LOG_LEVEL_DEBUG, + "Delivering MCAST message with seqid %d to pending delivery queue\n", + mcast->header.seqid); + +//printf ("Delivering MCAST from packet %d of %d of total %d seqid %d\n", mcast->packet_number, mcast->packet_count, mcast->packet_seq, mcast->header.seqid); + gmi_arut = i; + + /* + * Create pending delivery item + */ + pend_delv_item.iov_len = gmi_rtr_item_p->iov_len; + memcpy (&pend_delv_item.iovec, gmi_rtr_item_p->iovec, + sizeof (struct iovec) * gmi_rtr_item_p->iov_len); + assert (gmi_rtr_item_p->iov_len < MAXIOVS); + + assert (mcast->source.s_addr != 0); + pend_delv = pend_delv_find (mcast->source); + assert (pend_delv != 0); + assert (pend_delv->ip.s_addr != 0); + + if (mcast->packet_number == 0) { + pend_delv->seqid = mcast->header.seqid; + } + + /* + * Add pending delivery item to pending delivery queue + */ + queue_item_add (&pend_delv->queue, &pend_delv_item); + + /* + * If message is complete, attempt delivery of all messages + * that are currently outstanding + */ + if (mcast->packet_number == mcast->packet_count) { +//printf ("Starting delivery\n"); + delivery_outstanding += 1; + do { + delivered = user_deliver (); + if (delivered) { + delivery_outstanding -= 1; + } + } while (delivery_outstanding && delivered); + } + } +//printf ("Done delivering messages to pending queues\n"); +} + +/* + * recv message handler called when MCAST message type received + */ +static int message_handler_mcast ( + struct sockaddr_in *system_from, + struct iovec *iovec, + int iov_len, + int bytes_received) +{ + struct gmi_rtr_item gmi_rtr_item; + struct mcast *mcast; + + mcast = iovec[0].iov_base; + + /* + * Ignore multicasts for other configurations + * TODO shouldn't we enter gather here? + */ + if (memcmp (&mcast->memb_conf_id, + &memb_form_token_conf_id, sizeof (struct memb_conf_id)) != 0) { + + return (0); + } + + /* + * Add mcast message to rtr queue if not already in rtr queue + * otherwise free io vectors + */ + if (bytes_received > 0 && bytes_received < MESSAGE_SIZE_MAX && + sq_item_inuse (&queue_rtr_items, mcast->header.seqid) == 0) { + + /* + * Allocate new multicast memory block + * TODO we need to free this somewhere + */ + gmi_rtr_item.iovec[0].iov_base = malloc (bytes_received); + if (gmi_rtr_item.iovec[0].iov_base == 0) { + return (-1); /* error here is corrected by the algorithm */ + } + memcpy (gmi_rtr_item.iovec[0].iov_base, mcast, bytes_received); + gmi_rtr_item.iovec[0].iov_len = bytes_received; + assert (gmi_rtr_item.iovec[0].iov_len > 0); + assert (gmi_rtr_item.iovec[0].iov_len < MESSAGE_SIZE_MAX); + gmi_rtr_item.iov_len = 1; + + if (mcast->header.seqid > gmi_highest_seq) { + gmi_highest_seq = mcast->header.seqid; + } + + sq_item_add (&queue_rtr_items, &gmi_rtr_item, mcast->header.seqid); + } + + pending_queues_deliver (); + + return (0); +} + +static int message_handler_memb_attempt_join ( + struct sockaddr_in *system_from, + struct iovec *iov, + int iov_len, + int bytes_received) +{ + int token_lost; + int found; + int i; + + log_printf (LOG_LEVEL_NOTICE, "Got attempt join from %s\n", inet_ntoa (system_from->sin_addr)); + + for (token_lost = 0, i = 0; i < memb_list_entries; i++) { + if (memb_list[i].sin_addr.s_addr == system_from->sin_addr.s_addr && + memb_conf_id.rep.s_addr != system_from->sin_addr.s_addr) { + log_printf (LOG_LEVEL_DEBUG, "ATTEMPT JOIN, token lost, taking attempt join msg.\n"); + poll_timer_delete (*gmi_poll_handle, timer_orf_token_timeout); + timer_orf_token_timeout = 0; + memb_conf_id.rep.s_addr = memb_local_sockaddr_in.sin_addr.s_addr; + token_lost = 1; + break; + } + } + + /* + * Not representative + */ + if (token_lost == 0 && + memb_conf_id.rep.s_addr != memb_local_sockaddr_in.sin_addr.s_addr) { + + log_printf (LOG_LEVEL_NOTICE, "not the rep for this ring, not handling attempt join.\n"); + return (0); + } + + switch (memb_state) { + case MEMB_STATE_OPERATIONAL: + case MEMB_STATE_COMMIT: + memb_state_gather_enter (); + /* + * Do NOT place break here, immediately execute gather attempt join + */ + + case MEMB_STATE_GATHER: + log_printf (LOG_LEVEL_DEBUG, "ATTEMPT JOIN: state gather\n"); + for (found = 0, i = 0; i < memb_gather_set_entries; i++) { + if (memb_gather_set[i].s_addr == system_from->sin_addr.s_addr) { + found = 1; + } + } + + if (found == 0) { + memb_gather_set[memb_gather_set_entries++].s_addr = system_from->sin_addr.s_addr; + /* + * Sort gather set + */ + qsort (memb_gather_set, memb_gather_set_entries, + sizeof (struct in_addr), in_addr_compare); + + } + break; + + default: + // TODO what about other states + log_printf (LOG_LEVEL_ERROR, "memb_attempt_join: EVS or FORM state attempt join occured %d\n", memb_state); + } + + return (0); +} + +static int message_handler_memb_join ( + struct sockaddr_in *system_from, + struct iovec *iovec, + int iov_len, + int bytes_received) +{ + struct memb_join *memb_join; + int commit_entry; + int found; + int consensus; + + /* + * Not representative + */ + if (memb_conf_id.rep.s_addr != memb_local_sockaddr_in.sin_addr.s_addr) { + log_printf (LOG_LEVEL_DEBUG, "not the rep for this ring, not handling join.\n"); + return (0); + } + + switch (memb_state) { + case MEMB_STATE_OPERATIONAL: + case MEMB_STATE_GATHER: + memb_state_commit_enter (); + /* + * do not place break in this case, immediately enter COMMIT state + */ + + case MEMB_STATE_COMMIT: + log_printf (LOG_LEVEL_DEBUG, "JOIN in commit\n"); + memb_join = (struct memb_join *)iovec[0].iov_base; + /* + * Find gather set that matches the system message was from + */ + for (found = 0, commit_entry = 0; commit_entry < memb_commit_set_entries; commit_entry++) { + if (system_from->sin_addr.s_addr == memb_commit_set[commit_entry].rep.sin_addr.s_addr) { + found = 1; + break; + } + } + + /* + * Add system from to commit sets if not currently in commit set + */ + if (found == 0) { + memcpy (&memb_commit_set[commit_entry].rep, system_from, sizeof (struct sockaddr_in)); + memb_commit_set_entries++; + } + + /* + * Set gather join data + */ + memcpy (memb_commit_set[commit_entry].join_rep_list, memb_join->active_rep_list, + sizeof (struct in_addr) * memb_join->active_rep_list_entries); + memb_commit_set[commit_entry].join_rep_list_entries = memb_join->active_rep_list_entries; + + /* + * Union all entries into the gather set (join_rep_list[0]) + */ + memb_state_commit_union (commit_entry); + + /* + * Send JOIN message, but only if gather set has changed + */ + memb_join_send (); + + /* + * If consensus, transition to FORM + */ + memb_print_commit_set (); + + consensus = memb_state_consensus_commit (); + if (consensus) { + log_printf (LOG_LEVEL_NOTICE, "CONSENSUS reached!\n"); + if (memb_local_sockaddr_in.sin_addr.s_addr == memb_gather_set[0].s_addr) { + log_printf (LOG_LEVEL_DEBUG, "This node responsible for sending the FORM token.\n"); + + poll_timer_delete (*gmi_poll_handle, timer_memb_state_commit_timeout); + timer_memb_state_commit_timeout = 0; + + memb_form_token_send_initial (); + } + } + break; + /* + * All other cases are ignored on JOINs + */ + case MEMB_STATE_FORM: + log_printf (LOG_LEVEL_WARNING, "JOIN in form, ignoring since consensus reached in state machine.\n"); + break; + + default: + // TODO HANDLE THIS CASE + log_printf (LOG_LEVEL_DEBUG, "memb_join: DEFAULT case %d, shouldn't happen!!\n", memb_state); + break; + } + + return (0); +} + +static int message_handler_memb_form_token ( + struct sockaddr_in *system_from, + struct iovec *iovec, + int iov_len, + int bytes_received) +{ + int i; + int local = 0; + int res = 0; + int swallow_form = 0; + +printf ("Got membership form token\n"); + memcpy (&memb_form_token, iovec->iov_base, sizeof (struct memb_form_token)); + + poll_timer_delete (*gmi_poll_handle, timer_form_token_timeout); + timer_form_token_timeout = 0; + + + switch (memb_state) { + case MEMB_STATE_OPERATIONAL: + case MEMB_STATE_COMMIT: + memb_state = MEMB_STATE_FORM; + poll_timer_delete (*gmi_poll_handle, timer_memb_state_commit_timeout); + timer_memb_state_commit_timeout = 0; + /* + * Add member to entry + */ + memb_form_token.member_list[memb_form_token.member_list_entries].s_addr = + memb_local_sockaddr_in.sin_addr.s_addr; + memb_form_token.member_list_entries++; + /* + * Modify the conf_id as necessary + */ + memb_form_token_conf_desc_build (&memb_form_token); + + /* + * Stop token timeout timer from firing + * If we are in FORM state, a previous FORM state member + * may have captured the ORF token and swallowed it + */ + poll_timer_delete (*gmi_poll_handle, timer_orf_token_timeout); + timer_orf_token_timeout = 0; + break; + + case MEMB_STATE_FORM: + memb_state = MEMB_STATE_EVS; + memb_form_token_update_highest_seq (&memb_form_token); + + /* + * FORM token has rotated once, now install local variables + * + * Set barrier sequence number + * Set original arut + */ + gmi_barrier_seq = 0; +printf ("conf_desc_list %d\n", memb_form_token.conf_desc_list_entries); + for (i = 0; i < memb_form_token.conf_desc_list_entries; i++) { +printf ("highest seq %d %d\n", i, memb_form_token.conf_desc_list[i].highest_seq); + if (gmi_barrier_seq < memb_form_token.conf_desc_list[i].highest_seq) { + gmi_barrier_seq = memb_form_token.conf_desc_list[i].highest_seq; +printf ("setting barrier seq to %d\n", gmi_barrier_seq); + } + } + gmi_barrier_seq += 1; +printf ("setting barrier seq to %d\n", gmi_barrier_seq); + gmi_original_arut = gmi_arut; + + /* + * Determine next ORF target + */ + for (i = 0; i < memb_form_token.member_list_entries; i++) { + if (memb_local_sockaddr_in.sin_addr.s_addr == memb_form_token.member_list[i].s_addr) { + memb_next.sin_addr.s_addr = + memb_form_token.member_list[(i + 1) % memb_form_token.member_list_entries].s_addr; + memb_next.sin_family = AF_INET; + memb_next.sin_port = sockaddr_in_mcast.sin_port; + } + } + break; + + case MEMB_STATE_EVS: + log_printf (LOG_LEVEL_DEBUG, "Swallowing FORM token in EVS state.\n"); + printf ("FORM CONF ENTRIES %d\n", memb_form_token.conf_desc_list_entries); + orf_token_send_initial(); + swallow_form = 1; + return (0); + + default: + // TODO + log_printf (LOG_LEVEL_ERROR, "memb_form_token: default case, shouldn't happen.\n"); + return (0); + } + + /* + * Find next member + */ + for (i = 0; i < memb_list_entries; i++) { + if (memb_list[i].sin_addr.s_addr == memb_local_sockaddr_in.sin_addr.s_addr) { + local = 1; + break; + } + } + + if (memb_list_entries == 0) { /* 0 or 1 members and we are local */ + local = 1; + } + + if (local && (i + 1 < memb_list_entries)) { + memb_next.sin_addr.s_addr = memb_list[i + 1].sin_addr.s_addr; + } else { + /* + * Find next representative + */ + for (i = 0; i < memb_form_token.rep_list_entries; i++) { + if (memb_conf_id.rep.s_addr == + memb_form_token.rep_list[i].s_addr) { + break; + } + } + memb_next.sin_addr.s_addr = + memb_form_token.rep_list[(i + 1) % memb_form_token.rep_list_entries].s_addr; + } + memb_next.sin_family = AF_INET; + memb_next.sin_port = sockaddr_in_mcast.sin_port; + if (swallow_form == 0) { + res = memb_form_token_send (&memb_form_token); + } + return (res); +} + +int recv_handler (poll_handle handle, int fd, int revents, void *data) +{ + struct msghdr msg_recv; + struct message_header *message_header; + struct sockaddr_in system_from; + int res = 0; + int bytes_received; + + /* + * Receive datagram + */ + msg_recv.msg_name = &system_from; + msg_recv.msg_namelen = sizeof (struct sockaddr_in); + msg_recv.msg_iov = &gmi_iov_recv; + msg_recv.msg_iovlen = 1; + msg_recv.msg_control = 0; + msg_recv.msg_controllen = 0; + msg_recv.msg_flags = 0; + + bytes_received = recvmsg (gmi_fd, &msg_recv, MSG_NOSIGNAL | MSG_DONTWAIT); + if (bytes_received == -1) { + return (0); + } else { + stats_recv += bytes_received; + } + + /* + * Authenticate datagram + */ + res = gmi_msg_auth (msg_recv.msg_iov, msg_recv.msg_iovlen); + if (res == -1) { + return 0; + } + + if (stats_tv_start.tv_usec == 0) { + gettimeofday (&stats_tv_start, NULL); + } + + /* + * Handle incoming message + */ + message_header = (struct message_header *)msg_recv.msg_iov[0].iov_base; + gmi_message_handlers.handler_functions[message_header->type] ( + &system_from, + msg_recv.msg_iov, + msg_recv.msg_iovlen, + bytes_received); + + return (0); +} diff --git a/exec/gmi.h b/exec/gmi.h index e69de29b..08caf467 100644 --- a/exec/gmi.h +++ b/exec/gmi.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 GMI_H_DEFINED +#define GMI_H_DEFINED + +#include "poll.h" + +#define MESSAGE_SIZE_MAX 256000 + +#define GMI_PRIO_HIGH 0 +#define GMI_PRIO_MED 1 +#define GMI_PRIO_LOW 2 + +typedef int gmi_join_handle; + +struct gmi_groupname { + char groupname[16]; +}; + +poll_handle *gmi_poll_handle; + +/* + * Group messaging interface + * depends on poll abstraction, POSIX, IPV4 or IPV6 + */ +int gmi_init ( + struct sockaddr_in *sockaddr_mcast, + struct sockaddr_in *sockaddr_bindnet, + poll_handle *poll_handle, + struct sockaddr_in *bound_to); + + +int gmi_join ( + struct gmi_groupname *groupname, + void (*deliver_fn) ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len), + void (*confchg_fn) ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries), + gmi_join_handle *handle_out); + +int gmi_leave ( + gmi_join_handle handle_join); + +int gmi_mcast ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len, + int priority); + +#endif /* GMI_H_DEFINED */ diff --git a/exec/handlers.h b/exec/handlers.h index e69de29b..7551ce00 100644 --- a/exec/handlers.h +++ b/exec/handlers.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 HANDLERS_H_DEFINED +#define HANDLERS_H_DEFINED + +#include + +struct service_handler { + int (**libais_handler_fns) (int fd, void *); + int libais_handler_fns_count; + int (**aisexec_handler_fns) (int fd, void *); + int aisexec_handler_fns_count; + int (*confchg_fn) ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries); + int (*libais_init_fn) (int fd, void *); + int (*libais_exit_fn) (int fd); + int (*aisexec_init_fn) (void); +}; + +#ifdef COMPILE_OUT +extern struct libais_message_handlers libais_message_handlers[]; + +extern struct aisexec_message_handlers aisexec_message_handlers; +#endif + +#endif /* HANDLERS_H_DEFINED */ diff --git a/exec/log/print.c b/exec/log/print.c index e69de29b..f79e6751 100644 --- a/exec/log/print.c +++ b/exec/log/print.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include + +#include "print.h" + +int log_fd = 0; + +struct sockaddr_un syslog_sockaddr = { + sun_family: AF_UNIX, + sun_path: "/dev/log" +}; + +/* + * logging printf + */ +void +internal_log_printf (int level, char *string, ...) +{ + va_list ap; + char newstring[1024]; + struct msghdr msg_log; + struct iovec iov_log; + int res; + + va_start(ap, string); + + sprintf (newstring, "L(%x): %s", level, string); + vfprintf(stderr, newstring, ap); + + va_end(ap); + + if (log_fd == 0) { + log_fd = socket (AF_UNIX, SOCK_DGRAM, 0); + } + + iov_log.iov_base = newstring; + iov_log.iov_len = strlen (newstring) + 1; + + msg_log.msg_iov = &iov_log; + msg_log.msg_iovlen = 1; + msg_log.msg_name = &syslog_sockaddr; + msg_log.msg_namelen = sizeof (syslog_sockaddr); + msg_log.msg_control = 0; + msg_log.msg_controllen = 0; + msg_log.msg_flags = 0; + + res = sendmsg (log_fd, &msg_log, MSG_NOSIGNAL | MSG_DONTWAIT); +printf ("res is %d\n", res); +} + +int main (void) { + log_printf (LOG_LEVEL_ERROR, "This is error string 1=%d\n", 1); +} diff --git a/exec/log/print.h b/exec/log/print.h index e69de29b..a8889327 100644 --- a/exec/log/print.h +++ b/exec/log/print.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 PRINT_H_DEFINED +#define PRINT_H_DEFINED + +#include "../include/ais_types.h" + + +#define LOG_LEVEL_ERROR 1 +#define LOG_LEVEL_WARNING 2 +#define LOG_LEVEL_NOTICE 3 +#define LOG_LEVEL_DEBUG 4 + +extern void internal_log_printf (int level, char *string, ...); + +/* + * The optimizer will remove DEBUG logging messages in production builds + */ +#ifdef DEBUG +#define log_printf(level,format,args...) { internal_log_printf (level,format,##args); } +#else +#define log_printf(level,format,args...) { if (level != LOG_LEVEL_DEBUG) internal_log_printf (level,format,##args); } +#endif + +extern void printSaNameT (char *format, SaNameT *name); + +extern void printSaClmNodeAddressT (char *format, SaClmNodeAddressT *nodeAddress); + +extern void printSaClmClusterNodeT (char *description, SaClmClusterNodeT *clusterNode); + +extern void saAmfPrintGroups (void); + +#endif /* PRINT_H_DEFINED */ diff --git a/exec/main.c b/exec/main.c index e69de29b..93bee608 100644 --- a/exec/main.c +++ b/exec/main.c @@ -0,0 +1,722 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_msg.h" +#include "../include/list.h" +#include "../include/queue.h" +#include "poll.h" +#include "gmi.h" +#include "mempool.h" +#include "parse.h" +#include "main.h" +#include "handlers.h" +#include "clm.h" +#include "amf.h" +#include "ckpt.h" +#include "print.h" + +#define SERVER_BACKLOG 5 + +int connection_entries = 0; +struct connection *connections = 0; +int gid_valid = 20; + +struct gmi_groupname aisexec_groupname = { "0123" }; + +/* + * All service handlers in the AIS + */ +struct service_handler *ais_service_handlers[] = { + &clm_service_handler, + &amf_service_handler, + &ckpt_service_handler, + &ckpt_checkpoint_service_handler, + &ckpt_sectioniterator_service_handler +}; + +#define AIS_SERVICE_HANDLERS_COUNT 5 +#define AIS_SERVICE_HANDLER_AISEXEC_FUNCTIONS_MAX 40 + +static int poll_handler_libais_deliver (poll_handle handle, int fd, int revent, void *data); + +static inline void ais_done (int err) +{ + log_printf (LOG_LEVEL_ERROR, "AIS Executive exiting.\n"); + exit (1); +} + +static inline int init_connection_entry (int fd) +{ + int res; + + memset (&connections[fd], 0, sizeof (struct connection)); + connections[fd].active = 1; + res = queue_init (&connections[fd].outq, SIZEQUEUE, sizeof (struct outq_item)); + if (res != 0) { + goto error_exit; + } + connections[fd].inb = malloc (sizeof (char) * SIZEINB); + if (connections[fd].inb == 0) { + queue_free (&connections[fd].outq); + goto error_exit; + } + return (0); + +error_exit: + return (-1); +} + +/* + * Grows the connections table to fd + 1 in size clearing new entries + */ +static inline int grow_connections_table (int fd) +{ + struct connection *conn_temp; + + if (fd + 1 > connection_entries) { + conn_temp = mempool_realloc (connections, (fd + 1) * sizeof (struct connection)); + if (conn_temp == 0) { + return (-1); + } + connections = conn_temp; + memset (&connections[connection_entries], 0, + (fd - connection_entries + 1) * sizeof (struct connection)); + connection_entries = fd + 1; + } + return (0); +} + +struct sockaddr_in this_ip; +#define LOCALHOST_IP inet_addr("127.0.0.1") + +char *socketname = "libais.socket"; + +static void libais_disconnect (int fd) +{ + int i; + + close (fd); + connections[fd].active = 0; + queue_free (&connections[fd].outq); + free (connections[fd].inb); + + for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) { + if (ais_service_handlers[i]->libais_exit_fn) { + ais_service_handlers[i]->libais_exit_fn (fd); + } + } + + poll_dispatch_delete (aisexec_poll_handle, fd); +} + +extern int libais_send_response (int s, void *msg, int mlen) +{ + struct queue *outq; + char *cmsg; + int res; + int queue_empty; + struct outq_item *queue_item; + struct outq_item queue_item_out; + struct msghdr msg_send; + struct iovec iov_send; + + outq = &connections[s].outq; + + msg_send.msg_iov = &iov_send; + msg_send.msg_name = 0; + msg_send.msg_namelen = 0; + msg_send.msg_iovlen = 1; + msg_send.msg_control = 0; + msg_send.msg_controllen = 0; + msg_send.msg_flags = 0; + + if (queue_is_full (outq)) { + log_printf (LOG_LEVEL_ERROR, "queue is full.\n"); + ais_done (1); + } + while (!queue_is_empty (outq)) { + queue_item = queue_item_get (outq); + iov_send.iov_base = (void *)connections[s].byte_start; + iov_send.iov_len = queue_item->mlen; + +retry_sendmsg: + res = sendmsg (s, &msg_send, MSG_DONTWAIT | MSG_NOSIGNAL); + if (res == -1 && errno == EINTR) { + goto retry_sendmsg; + } + if (res == -1 && errno == EAGAIN) { + break; /* outgoing kernel queue full, ais_done while not empty */ + } + if (res == -1) { + return (-1); /* message couldn't be sent */ + } + + /* + * Message sent, try sending another message + */ + queue_item_remove (outq); + connections[s].byte_start = 0; + mempool_free (queue_item->msg); + } /* while queue not empty */ + + res = 0; + queue_empty = queue_is_empty (outq); + /* + * Send requested message + */ + if (queue_empty) { + iov_send.iov_base = msg; + iov_send.iov_len = mlen; +retry_sendmsg_two: + res = sendmsg (s, &msg_send, MSG_DONTWAIT | MSG_NOSIGNAL); + if (res == -1 && errno == EINTR) { + goto retry_sendmsg_two; + } + if (res == -1 && errno != EAGAIN) { + return (-1); + } + } + + /* + * If res == -1 , errrno == EAGAIN which means kernel queue full + */ + if (res == -1) { + cmsg = mempool_malloc (mlen); + if (cmsg == 0) { + ais_done (1); + } + queue_item_out.msg = cmsg; + queue_item_out.mlen = mlen; + memcpy (cmsg, msg, mlen); + queue_item_add (outq, &queue_item_out); + } + return (0); +} + +static int poll_handler_libais_accept ( + poll_handle handle, + int fd, + int revent, + void *data) +{ + int addrlen; + struct sockaddr_un un_addr; + int new_fd; + int on = 1; + 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) { + log_printf (LOG_LEVEL_ERROR, "ERROR: Could not accept Library connection: %s\n", strerror (errno)); + return (0); /* This is an error, but -1 would indicate disconnect from poll loop */ + } + + /* + * Valid accept + */ + + /* + * Request credentials of sender provided by kernel + */ + setsockopt(new_fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)); + + log_printf (LOG_LEVEL_DEBUG, "connection received from libais client %d.\n", new_fd); + /* + * Generate new connections array + */ + res = grow_connections_table (new_fd); + if (res == -1) { + close (new_fd); + return (0); /* This is an error, but -1 would indicate disconnect from poll */ + + } + + res = init_connection_entry (new_fd); + if (res == -1) { + close (new_fd); + return (0); /* This is an error, but -1 would indicate disconnect from poll */ + } + poll_dispatch_add (aisexec_poll_handle, new_fd, POLLIN, 0, poll_handler_libais_deliver); + + connections[new_fd].service = SOCKET_SERVICE_INIT; + memcpy (&connections[new_fd].ais_ci.un_addr, &un_addr, sizeof (struct sockaddr_un)); + return (0); +} + +static int poll_handler_libais_deliver (poll_handle handle, int fd, int revent, void *data) +{ + int res; + struct message_header *header; + int service; + struct msghdr msg_recv; + struct iovec iov_recv; + struct cmsghdr *cmsg; + char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))]; + struct ucred *cred; + int on = 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_flags = 0; + + if (connections[fd].authenticated) { + msg_recv.msg_control = 0; + msg_recv.msg_controllen = 0; + } else { + msg_recv.msg_control = (void *)cmsg_cred; + msg_recv.msg_controllen = sizeof (cmsg_cred); + } + + iov_recv.iov_base = &connections[fd].inb[connections[fd].inb_start]; + iov_recv.iov_len = (SIZEINB) - connections[fd].inb_start; + assert (iov_recv.iov_len != 0); +//printf ("inb start inb inuse %d %d\n", connections[fd].inb_start, connections[fd].inb_inuse); + +retry_recv: + res = recvmsg (fd, &msg_recv, MSG_DONTWAIT | MSG_NOSIGNAL); +//printf ("received %d bytes\n", res); + if (res == -1 && errno == EINTR) { + goto retry_recv; + } else + if (res == -1) { + goto error_exit; + } else + if (res == 0) { + goto error_exit; + return (-1); + } + + /* + * Authenticate if this connection has not been authenticated + */ + if (connections[fd].authenticated == 0) { + cmsg = CMSG_FIRSTHDR (&msg_recv); + cred = (struct ucred *)CMSG_DATA (cmsg); + if (cred) { + if (cred->uid == 0 || cred->gid == gid_valid) { + setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)); + connections[fd].authenticated = 1; + } + } + if (connections[fd].authenticated == 0) { + log_printf (LOG_LEVEL_SECURITY, "Connection not authenticated because gid is %d, expecting %d\n", cred->gid, gid_valid); + } + } + /* + * Dispatch all messages received in recvmsg that can be dispatched + * sizeof (struct message_header) needed at minimum to do any processing + */ + connections[fd].inb_inuse += res; + connections[fd].inb_start += res; + + while (connections[fd].inb_inuse >= sizeof (struct message_header) && res != -1) { + header = (struct message_header *)&connections[fd].inb[connections[fd].inb_start - connections[fd].inb_inuse]; + + if (header->magic != MESSAGE_MAGIC) { + log_printf (LOG_LEVEL_SECURITY, "Invalid magic is %x should be %x\n", header->magic, MESSAGE_MAGIC); + res = -1; + goto error_exit; + } + + if (header->size > connections[fd].inb_inuse) { + break; + } + service = connections[fd].service; + + /* + * If this service is in init phase, initialize service + * else handle message using service handlers + */ + if (service == SOCKET_SERVICE_INIT) { + /* + * Initializing service + */ + res = ais_service_handlers[header->id]->libais_init_fn (fd, header); + } else { + /* + * Not an init service, but a standard service + */ + if (header->id < 0 || header->id > ais_service_handlers[service - 1]->libais_handler_fns_count) { + log_printf (LOG_LEVEL_SECURITY, "Invalid header id is %d min 0 max %d\n", + header->id, ais_service_handlers[service - 1]->libais_handler_fns_count); + res = -1; + goto error_exit; + } + + res = ais_service_handlers[service - 1]->libais_handler_fns[header->id](fd, header); + } + connections[fd].inb_inuse -= header->size; + } /* while */ + + if (connections[fd].inb_inuse == 0) { + connections[fd].inb_start = 0; + } else +// BUG if (connections[fd].inb_start + connections[fd].inb_inuse >= SIZEINB) { + if (connections[fd].inb_start >= SIZEINB) { + /* + * If in buffer is full, move it back to start + */ + memmove (connections[fd].inb, + &connections[fd].inb[connections[fd].inb_start - + connections[fd].inb_inuse], + sizeof (char) * connections[fd].inb_inuse); + connections[fd].inb_start = connections[fd].inb_inuse; + } + + + return (res); + +error_exit: + libais_disconnect (fd); + return (-1); /* remove entry from poll list */ +} + +extern void print_stats (void); + +void sigintr_handler (int signum) +{ + +#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 (LOG_LEVEL_DEBUG, "Memory pools:\n"); + for (i = 0; i < MEMPOOL_GROUP_SIZE; i++) { + log_printf (LOG_LEVEL_DEBUG, "order %d size %d inuse %d avail %d memory used %d\n", + i, 1<aisexec_handler_fns_count; j++) { + aisexec_handler_fns[aisexec_handler_fns_count++] = + ais_service_handlers[i]->aisexec_handler_fns[j]; + } + } + log_printf (LOG_LEVEL_DEBUG, "built %d handler functions\n", aisexec_handler_fns_count); +} + +char delivery_data[MESSAGE_SIZE_MAX]; + +static void deliver_fn ( + struct gmi_groupname *groupname, + struct iovec *iovec, + int iov_len) +{ + struct message_header *header; + int res; + int pos = 0; + int i; + + /* + * 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 = (struct message_header *)delivery_data; + } else { + header = iovec[0].iov_base; + } + res = aisexec_handler_fns[header->id](0, header); +} + +static void confchg_fn ( + struct sockaddr_in *member_list, int member_list_entries, + struct sockaddr_in *left_list, int left_list_entries, + struct sockaddr_in *joined_list, int joined_list_entries) +{ + int i; + + /* + * Call configure change for all APIs + */ + for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) { + if (ais_service_handlers[i]->confchg_fn) { + ais_service_handlers[i]->confchg_fn (member_list, member_list_entries, + left_list, left_list_entries, joined_list, joined_list_entries); + } + } +} + +static void aisexec_group_determine (void) { + struct group *group; + group = getgrnam ("ais"); + if (group == 0) { + log_printf (LOG_LEVEL_ERROR, "The 'ais' group is not found in /etc/group, please read the documentation.\n"); + ais_done (-1); + } + gid_valid = group->gr_gid; +} + +static void aisexec_mempool_init (void) +{ + int res; + + res = mempool_init (pool_sizes); + if (res == ENOMEM) { + log_printf (LOG_LEVEL_ERROR, "Couldn't allocate memory pools, not enough memory"); + ais_done (1); + } +} + +static void aisexec_tty_detach (void) +{ +#define DEBUG +#ifndef DEBUG + /* + * Disconnect from TTY if this is not a debug run + */ + switch (fork ()) { + case -1: + ais_done (1); + break; + case 0: + /* + * child which is disconnected, run this process + */ + break; + default: + exit (0); + break; + } +#endif +#undef DEBUG +} + +static void aisexec_service_handlers_init (void) +{ + int i; + /* + * Initialize all services + */ + for (i = 0; i < AIS_SERVICE_HANDLERS_COUNT; i++) { + if (ais_service_handlers[i]->aisexec_init_fn) { + ais_service_handlers[i]->aisexec_init_fn (); + } + } +} + +static void aisexec_libais_bind (int *server_fd) +{ + int libais_server_fd; + struct sockaddr_un un_addr; + int res; + + /* + * Create socket for libais clients, name socket, listen for connections + */ + libais_server_fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (libais_server_fd == -1) { + log_printf (LOG_LEVEL_ERROR ,"Cannot create libais client connections socket.\n"); + ais_done (1); + }; + + memset (&un_addr, 0, sizeof (struct sockaddr_un)); + un_addr.sun_family = AF_UNIX; + strcpy (un_addr.sun_path + 1, socketname); + + res = bind (libais_server_fd, (struct sockaddr *)&un_addr, sizeof (struct sockaddr_un)); + if (res) { + log_printf (LOG_LEVEL_ERROR, "ERROR: Could not bind AF_UNIX: %s.\n", strerror (errno)); + ais_done (1); + } + listen (libais_server_fd, SERVER_BACKLOG); + + *server_fd = libais_server_fd; +} + +static void aisexec_setscheduler (void) +{ + int res; + + res = sched_setscheduler (0, SCHED_RR, &sched_param); + if (res == -1) { + log_printf (LOG_LEVEL_ERROR, "WARNING: Could not set SCHED_RR at priority 99: %s\n", strerror (errno)); + } +} + +static void aisexec_mlockall (void) +{ + int res; + + res = mlockall (MCL_CURRENT | MCL_FUTURE); + if (res == -1) { + log_printf (LOG_LEVEL_ERROR, "WARNING: Could not lock memory of service to avoid page faults: %s\n", strerror (errno)); + }; +} + +int main (int argc, char **argv) +{ + int libais_server_fd; + int res; + struct sockaddr_in sockaddr_in_mcast; + struct sockaddr_in sockaddr_in_bindnet; + gmi_join_handle handle; + + + char *error_string; + + aisexec_group_determine (); + + aisexec_handler_fns_build (); + + aisexec_poll_handle = poll_create (); + + res = amfReadNetwork (&error_string, &sockaddr_in_mcast, &sockaddr_in_bindnet); + if (res == -1) { + log_printf (LOG_LEVEL_ERROR, error_string); + ais_done (1); + } + + + /* + * Initialize group messaging interface with multicast address + */ + gmi_init (&sockaddr_in_mcast, &sockaddr_in_bindnet, + &aisexec_poll_handle, &this_ip); + + aisexec_mempool_init (); + + res = amfReadGroups(&error_string); + if (res == -1) { + log_printf (LOG_LEVEL_ERROR, error_string); + ais_done (1); + } + + aisexec_tty_detach (); + + log_printf (LOG_LEVEL_NOTICE, "AIS Executive Service: Copyright (C) 2002-2004 MontaVista Software, Inc.\n"); + signal (SIGINT, sigintr_handler); + + aisexec_service_handlers_init (); + + aisexec_libais_bind (&libais_server_fd); + + res = grow_connections_table (libais_server_fd); + if (res == -1) { + log_printf (LOG_LEVEL_ERROR, "Could not allocate memory for listening socket.\n"); + ais_done (1); + } + + log_printf (LOG_LEVEL_NOTICE, "AIS Executive Service: started and ready to receive connections.\n"); + + /* + * Set round robin realtime scheduling with priority 99 + * Lock all memory to avoid page faults which may interrupt + * application healthchecking + */ + aisexec_setscheduler (); + + aisexec_mlockall (); + + /* + * Setup libais connection dispatch routine + */ + poll_dispatch_add (aisexec_poll_handle, libais_server_fd, + POLLIN, 0, poll_handler_libais_accept); + + /* + * Join multicast group and setup delivery + * and configuration change functions + */ + gmi_join (0, deliver_fn, confchg_fn, &handle); + + /* + * Start main processing loop + */ + poll_run (aisexec_poll_handle); + + return (0); +} diff --git a/exec/main.h b/exec/main.h index e69de29b..2c6b1bfa 100644 --- a/exec/main.h +++ b/exec/main.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include "../include/ais_types.h" +#include "poll.h" +#include "clm.h" +#include "amf.h" +#include "ckpt.h" + +#ifndef AIS_EXEC_H_DEFINED +#define AIS_EXEC_H_DEFINED + +/* + * Size of the queue (entries) for I/O's to the API over socket IPC. + */ +#define SIZEQUEUE 8192 + +enum socket_service_type { + SOCKET_SERVICE_INIT, + SOCKET_SERVICE_CLM, + SOCKET_SERVICE_AMF, + SOCKET_SERVICE_CKPT, + SOCKET_SERVICE_CKPT_CHECKPOINT, + SOCKET_SERVICE_CKPT_SECTIONITERATOR +}; + +struct aisexec_ci { + struct sockaddr_in in_addr; /* address of AF_INET socket, MUST BE FIRST IN STRUCTURE */ + SaClmClusterNodeT clusterNode; + SaClmClusterChangesT lastChange; + unsigned char authentication_key[16]; + int authenticated; +}; + +/* + * Connection information for AIS connections + */ +struct ais_ci { + struct sockaddr_un un_addr; /* address of AF_UNIX socket, MUST BE FIRST IN STRUCTURE */ + union { + struct aisexec_ci aisexec_ci; + struct libclm_ci libclm_ci; + struct libamf_ci libamf_ci; + struct libckpt_ci libckpt_ci; + } u; +}; + +struct outq_item { + void *msg; + size_t mlen; +}; + +#define SIZEINB MESSAGE_SIZE_MAX + +struct connection { + int active; /* Does this file descriptor have an active connection */ + char *inb; /* Input buffer for non-blocking reads */ + int inb_nextheader; /* Next message header starts here */ + int inb_start; /* Start location of input buffer */ + int inb_inuse; /* Bytes currently stored in input buffer */ + struct queue outq; /* Circular queue for outgoing requests */ + int byte_start; /* Byte to start sending from in head of queue */ + enum socket_service_type service;/* Type of service so dispatch knows how to route message */ + struct saAmfComponent *component; /* Component for which this connection relates to TODO shouldn't this be in the ci structure */ + int authenticated; /* Is this connection authenticated? */ + struct ais_ci ais_ci; /* libais connection information */ +}; + +extern int connection_entries; + +extern struct connection *connections; + +extern struct sockaddr_in this_ip; + +poll_handle aisexec_poll_handle; + +extern struct gmi_groupname aisexec_groupname; + +extern int libais_send_response (int s, void *msg, int mlen); + +#endif /* AIS_EXEC_H_DEFINED */ diff --git a/exec/mempool.c b/exec/mempool.c index e69de29b..361530e1 100644 --- a/exec/mempool.c +++ b/exec/mempool.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include + +#include "../include/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<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< +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/list.h" +#include "parse.h" +#include "mempool.h" + +DECLARE_LIST_INIT (saAmfGroupHead); + +typedef enum { + HEAD, + GROUP, + UNIT, + PROTECTION, + COMPONENT +} SaParsingT; + + +void setSaNameT (SaNameT *name, char *str) { + strncpy (name->value, str, SA_MAX_NAME_LENGTH); + if (strlen (name->value) > SA_MAX_NAME_LENGTH) { + name->length = SA_MAX_NAME_LENGTH; + } else { + name->length = strlen (str); + } +} + +int SaNameTisEqual (SaNameT *str1, char *str2) { + if (str1->length == strlen (str2)) { + return ((strncmp (str1->value, str2, str1->length)) == 0); + } else { + return 0; + } +} + +int SaNameTisNameT (SaNameT *name1, SaNameT *name2) { + if (name1->length == name2->length) { + return ((strncmp (name1->value, name2->value, name1->length)) == 0); + } else { + return 0; + } +} + +struct saAmfComponent *findComponent (SaNameT *name) +{ + struct list_head *AmfGroupList = 0; + struct list_head *AmfUnitList = 0; + struct list_head *AmfComponentList = 0; + + struct saAmfGroup *saAmfGroup = 0; + struct saAmfUnit *AmfUnit = 0; + struct saAmfComponent *AmfComponent = 0; + int found = 0; + + /* + * Search all groups + */ + for (AmfGroupList = saAmfGroupHead.next; + AmfGroupList != &saAmfGroupHead && found == 0; + AmfGroupList = AmfGroupList->next) { + + saAmfGroup = list_entry (AmfGroupList, + struct saAmfGroup, saAmfGroupList); + + /* + * Search all units + */ + for (AmfUnitList = saAmfGroup->saAmfUnitHead.next; + AmfUnitList != &saAmfGroup->saAmfUnitHead && found == 0; + AmfUnitList = AmfUnitList->next) { + + AmfUnit = list_entry (AmfUnitList, + struct saAmfUnit, saAmfUnitList); + + /* + * Search all components + */ + for (AmfComponentList = AmfUnit->saAmfComponentHead.next; + AmfComponentList != &AmfUnit->saAmfComponentHead && found == 0; + AmfComponentList = AmfComponentList->next) { + + AmfComponent = list_entry (AmfComponentList, + struct saAmfComponent, saAmfComponentList); + + if (SaNameTisNameT (name, &AmfComponent->name)) { + found = 1; + } + } + } + } + + if (found) { + return (AmfComponent); + } else { + return (0); + } +} +char * +strstr_rs (const char *haystack, const char *needle) +{ + char *end_address; + char *new_needle; + + new_needle = (char *)mempool_strdup (needle); + new_needle[strlen(new_needle) - 1] = '\0'; + + end_address = strstr (haystack, new_needle); + if (end_address) { + end_address += strlen (new_needle); + end_address = strstr (end_address, needle + strlen (new_needle)); + } + if (end_address) { + end_address += 1; /* skip past { or = */ + do { + if (*end_address == '\t' || *end_address == ' ') { + end_address++; + } else { + break; + } + } while (*end_address != '\0'); + } + + mempool_free (new_needle); + return (end_address); +} + +static char error_string_response[256]; + +int amfReadGroups (char **error_string) +{ + char line[255]; + FILE *fp; + SaParsingT current_parse = HEAD; + int line_number = 0; + char *loc; + int i; + + struct saAmfGroup *saAmfGroup = 0; + struct saAmfUnit *saAmfUnit = 0; + struct saAmfProtectionGroup *saAmfProtectionGroup = 0; + struct saAmfComponent *saAmfComponent = 0; + struct list_head *findAmfUnitList = 0; + struct list_head *findAmfComponentList = 0; + struct saAmfUnit *findAmfUnit = 0; + struct saAmfComponent *findAmfComponent = 0; + SaNameT componentName; + + fp = fopen ("/etc/ais/groups.conf", "r"); + if (fp == 0) { + *error_string = "ERROR: Could not open /etc/groups.conf file.\n"; + return (-1); + } + + while (fgets (line, 255, fp)) { + line_number += 1; + line[strlen(line) - 1] = '\0'; + /* + * Clear out white space and tabs + */ + for (i = strlen (line) - 1; i > -1; i--) { + if (line[i] == '\t' || line[i] == ' ') { + line[i] = '\0'; + } else { + break; + } + } + /* + * Clear out comments and empty lines + */ + if (line[0] == '#' || line[0] == '\0') { + continue; + } + + switch (current_parse) { + case HEAD: + if (strstr_rs (line, "group{")) { + saAmfGroup = (struct saAmfGroup *)mempool_malloc (sizeof (struct saAmfGroup)); + memset (saAmfGroup, 0, sizeof (struct saAmfGroup)); + list_init (&saAmfGroup->saAmfGroupList); + list_init (&saAmfGroup->saAmfUnitHead); + list_init (&saAmfGroup->saAmfProtectionGroupHead); + list_add (&saAmfGroup->saAmfGroupList, &saAmfGroupHead); + current_parse = GROUP; + } else + if (strcmp (line, "") == 0) { + } else { + goto parse_error; + } + break; + + case GROUP: + if ((loc = strstr_rs (line, "name=")) != 0) { + setSaNameT (&saAmfGroup->name, loc); + } else + if ((loc = strstr_rs (line, "model=")) != 0) { + if (strcmp (loc, "2n") == 0) { + saAmfGroup->model = GROUPCAPABILITYMODEL_2N; + } else + if (strcmp (loc, "nplusm") == 0) { + saAmfGroup->model = GROUPCAPABILITYMODEL_NPLUSM; + } else + if (strcmp (loc, "nway") == 0) { + printf ("nway redundancy model not supported.\n"); + goto parse_error; + } else + if (strcmp (loc, "nwayactive") == 0) { + printf ("nway active redundancy model not supported.\n"); + goto parse_error; + } else + if (strcmp (loc, "noredundancy") == 0) { + saAmfGroup->model = GROUPCAPABILITYMODEL_NOREDUNDANCY; + } else { + goto parse_error; + } + } else + if ((loc = strstr_rs (line, "active-units=")) != 0) { + saAmfGroup->saAmfActiveUnitsDesired = atoi (loc); + } else + if ((loc = strstr_rs (line, "backup-units=")) != 0) { + saAmfGroup->saAmfStandbyUnitsDesired = atoi (loc); + } else + if (strstr_rs (line, "unit{")) { + saAmfUnit = (struct saAmfUnit *)mempool_malloc (sizeof (struct saAmfUnit)); + memset (saAmfUnit, 0, sizeof (struct saAmfUnit)); + saAmfUnit->saAmfGroup = saAmfGroup; + + list_init (&saAmfUnit->saAmfComponentHead); + list_add (&saAmfUnit->saAmfUnitList, &saAmfGroup->saAmfUnitHead); + current_parse = UNIT; + } else + if (strstr_rs (line, "protection{")) { + saAmfProtectionGroup = (struct saAmfProtectionGroup *)mempool_malloc (sizeof (struct saAmfProtectionGroup)); + memset (saAmfProtectionGroup, 0, sizeof (struct saAmfProtectionGroup)); + list_init (&saAmfProtectionGroup->saAmfMembersHead); + list_init (&saAmfProtectionGroup->saAmfProtectionGroupList); + list_add (&saAmfProtectionGroup->saAmfProtectionGroupList, &saAmfGroup->saAmfProtectionGroupHead); + + current_parse = PROTECTION; + } else + if (strstr_rs (line, "}")) { + current_parse = HEAD; + } else { + goto parse_error; + } + break; + + case UNIT: + if ((loc = strstr_rs (line, "name=")) != 0) { + setSaNameT (&saAmfUnit->name, loc); + } else + if ((loc = strstr_rs (line, "component{")) != 0) { + saAmfComponent = (struct saAmfComponent *)mempool_malloc (sizeof (struct saAmfComponent)); + memset (saAmfComponent, 0, sizeof (struct saAmfComponent)); + saAmfComponent->saAmfUnit = saAmfUnit; + saAmfComponent->currentReadinessState = SA_AMF_OUT_OF_SERVICE; + saAmfComponent->newReadinessState = SA_AMF_OUT_OF_SERVICE; + saAmfComponent->currentHAState = SA_AMF_QUIESCED; + saAmfComponent->newHAState = SA_AMF_QUIESCED; + saAmfComponent->healthcheckInterval = 100; + list_init (&saAmfComponent->saAmfComponentList); + list_init (&saAmfComponent->saAmfProtectionGroupList); + list_add (&saAmfComponent->saAmfComponentList, &saAmfUnit->saAmfComponentHead); + + current_parse = COMPONENT; + } else + if (strstr_rs (line, "}")) { + current_parse = GROUP; + } else { + goto parse_error; + } + break; + + case COMPONENT: + if ((loc = strstr_rs (line, "name=")) != 0) { + setSaNameT (&saAmfComponent->name, loc); + } else + if ((loc = strstr_rs (line, "model=")) != 0) { + if (strcmp (loc, "x_active_and_y_standby") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE_AND_Y_STANDBY; + } else + if (strcmp (loc, "x_active_or_y_standby") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE_OR_Y_STANDBY; + } else + if (strcmp (loc, "1_active_or_y_standby") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE_OR_Y_STANDBY; + } else + if (strcmp (loc, "1_active_or_1_standby") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE_OR_1_STANDBY; + } else + if (strcmp (loc, "x_active") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE; + } else + if (strcmp (loc, "1_active") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE; + } else + if (strcmp (loc, "no_active") == 0) { + saAmfComponent->componentCapabilityModel = SA_AMF_COMPONENT_CAPABILITY_NO_ACTIVE; + } else { + goto parse_error; + } + } else + if (strstr_rs (line, "}")) { + current_parse = UNIT; + } else { + goto parse_error; + } + break; + + case PROTECTION: + if ((loc = strstr_rs (line, "name=")) != 0) { + setSaNameT (&saAmfProtectionGroup->name, loc); + } else + if ((loc = strstr_rs (line, "member=")) != 0) { + for (findAmfUnitList = saAmfGroup->saAmfUnitHead.next; + findAmfUnitList != &saAmfGroup->saAmfUnitHead; + findAmfUnitList = findAmfUnitList->next) { + + findAmfUnit = list_entry (findAmfUnitList, + struct saAmfUnit, saAmfUnitList); + for (findAmfComponentList = findAmfUnit->saAmfComponentHead.next; + findAmfComponentList != &findAmfUnit->saAmfComponentHead; + findAmfComponentList = findAmfComponentList->next) { + + findAmfComponent = list_entry (findAmfComponentList, + struct saAmfComponent, saAmfComponentList); + + if (SaNameTisEqual (&findAmfComponent->name, loc)) { + list_add (&findAmfComponent->saAmfProtectionGroupList, + &saAmfProtectionGroup->saAmfMembersHead); + } + } + /* + * Connect component to protection group + */ + setSaNameT (&componentName, loc); + saAmfComponent = findComponent (&componentName); + saAmfComponent->saAmfProtectionGroup = saAmfProtectionGroup; + } + } else + if (strstr_rs (line, "}")) { + current_parse = GROUP; + } else { + goto parse_error; + } + break; + + default: + printf ("Invalid state\n"); + goto parse_error; + break; + } + } + + fclose (fp); + return (0); + +parse_error: + sprintf (error_string_response, + "ERROR: parse error at /etc/groups.conf:%d\n", line_number); + + *error_string = error_string_response; + fclose (fp); + return (-1); +} + +int amfReadNetwork (char **error_string, + struct sockaddr_in *mcast_addr, + struct sockaddr_in *bindnet_addr) +{ + char line[255]; + FILE *fp; + int res = 0; + int line_number = 0; + + + mcast_addr->sin_family = AF_INET; + fp = fopen ("/etc/ais/network.conf", "r"); + + while (fgets (line, 255, fp)) { + line_number += 1; + if (strncmp ("mcastaddr:", line, strlen ("mcastaddr:")) == 0) { + res = inet_aton (&line[strlen("mcastaddr:")], &mcast_addr->sin_addr); + } else + if (strncmp ("bindnetaddr:", line, strlen ("bindnetaddr:")) == 0) { + res = inet_aton (&line[strlen("bindnetaddr:")], &bindnet_addr->sin_addr); + } else + if (strncmp ("mcastport:", line, strlen ("mcastport:")) == 0) { + res = mcast_addr->sin_port = atoi (&line[strlen("mcastport:")]); + } else { + res = 0; + break; + } + if (res == 0) { + sprintf (error_string_response, + "ERROR: parse error at /etc/ais/network.conf:%d\n", line_number); + *error_string = error_string_response; + res = -1; + break; + } + res = 0; + } + + + fclose (fp); + return (res); +} diff --git a/exec/parse.h b/exec/parse.h index e69de29b..99cdd82e 100644 --- a/exec/parse.h +++ b/exec/parse.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include "../include/ais_types.h" +#include "../include/list.h" +#include "poll.h" + +#ifndef PARSE_H_DEFINED +#define PARSE_H_DEFINED + +typedef enum { + GROUPCAPABILITYMODEL_2N, + GROUPCAPABILITYMODEL_NPLUSM, + GROUPCAPABILITYMODEL_NWAY, + GROUPCAPABILITYMODEL_NWAYACTIVE, + GROUPCAPABILITYMODEL_NOREDUNDANCY +} SaAmfGroupCapabilityModelT; + +enum amfOperationalAdministrativeState { + AMF_DISABLED_UNLOCKED = 0, + AMF_DISABLED_LOCKED = 1, + AMF_ENABLED_UNLOCKED = 2, + AMF_ENABLED_STOPPING = 3 +}; + +struct saAmfUnit { + SaNameT name; + struct list_head saAmfComponentHead; + struct list_head saAmfUnitList; + enum amfOperationalAdministrativeState operationalAdministrativeState; + struct saAmfGroup *saAmfGroup; +}; + +struct saAmfProtectionGroup { + SaNameT name; + struct list_head saAmfMembersHead; + struct list_head saAmfProtectionGroupList; +}; + +struct saAmfGroup { + SaNameT name; + SaAmfGroupCapabilityModelT model; + SaUint32T saAmfActiveUnitsDesired; + SaUint32T saAmfStandbyUnitsDesired; + struct list_head saAmfGroupList; + struct list_head saAmfProtectionGroupHead; + struct list_head saAmfUnitHead; +}; + +/* + * State machines for states in AMF + */ +enum amfOperationalState { + AMF_OPER_DISABLED, + AMF_OPER_ENABLED +}; + +enum amfAdministrativeState { + AMF_ADMIN_UNLOCKED, + AMF_ADMIN_LOCKED, + AMF_ADMIN_STOPPING +}; + +enum amfEnabledUnlockedState { + AMF_ENABLED_UNLOCKED_INITIAL = 0, + AMF_ENABLED_UNLOCKED_IN_SERVICE_REQUESTED, + AMF_ENABLED_UNLOCKED_IN_SERVICE_COMPLETED, + AMF_ENABLED_UNLOCKED_ACTIVE_REQUESTED, + AMF_ENABLED_UNLOCKED_ACTIVE_COMPLETED, + AMF_ENABLED_UNLOCKED_STANDBY_REQUESTED, + AMF_ENABLED_UNLOCKED_STANDBY_COMPLETED, +}; + +enum amfDisabledUnlockedState { + AMF_DISABLED_UNLOCKED_REGISTEREDORERRORCANCEL = 0, + AMF_DISABLED_UNLOCKED_FAILED, + AMF_DISABLED_UNLOCKED_QUIESCED_REQUESTED, + AMF_DISABLED_UNLOCKED_QUIESCED_COMPLETED, + AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_REQUESTED, + AMF_DISABLED_UNLOCKED_OUT_OF_SERVICE_COMPLETED +}; + +enum amfDisabledLockedState { + AMF_DISABLED_LOCKED_INITIAL = 0, + AMF_DISABLED_LOCKED_QUIESCED_REQUESTED, + AMF_DISABLED_LOCKED_QUIESCED_COMPLETED, + AMF_DISABLED_LOCKED_OUT_OF_SERVICE_REQUESTED, + AMF_DISABLED_LOCKED_OUT_OF_SERVICE_COMPLETED +}; + +enum amfEnabledStoppingState { + AMF_ENABLED_STOPPING_INITIAL = 0, + AMF_ENABLED_STOPPING_STOPPING_REQUESTED, + AMF_ENABLED_STOPPING_STOPPING_COMPLETED, +}; +struct saAmfComponent { + int registered; + int local; + int fd; + SaNameT name; + SaAmfReadinessStateT currentReadinessState; + SaAmfReadinessStateT newReadinessState; + SaAmfHAStateT currentHAState; + SaAmfHAStateT newHAState; + enum amfEnabledUnlockedState enabledUnlockedState; + enum amfDisabledUnlockedState disabledUnlockedState; + SaAmfComponentCapabilityModelT componentCapabilityModel; + SaAmfProbableCauseT probableCause; + int healthcheckInterval; + poll_timer_handle timer_healthcheck; + int healthcheck_outstanding; + struct saAmfComponent *saAmfProxyComponent; + struct list_head saAmfComponentList; + struct list_head saAmfProtectionGroupList; + struct saAmfUnit *saAmfUnit; + struct saAmfProtectionGroup *saAmfProtectionGroup; +}; + +extern struct list_head saAmfGroupHead; + +extern struct saAmfComponent *findComponent (SaNameT *name); + +extern int SaNameTisNameT (SaNameT *name1, SaNameT *name2); + +extern int amfReadGroups (char **error_string); + +extern int amfReadNetwork (char **error_string, struct sockaddr_in *mcast_addr, struct sockaddr_in *bindnet_addr); + +#endif /* PARSE_H_DEFINED */ diff --git a/exec/poll.c b/exec/poll.c index e69de29b..61d514a8 100644 --- a/exec/poll.c +++ b/exec/poll.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include + +#include "poll.h" +#include "../include/list.h" +#include "tlist.h" + +typedef int (*dispatch_fn_t) (poll_handle poll_handle, int fd, int revents, void *data); + +struct poll_instance { + struct pollfd *ufds; + int nfds; + dispatch_fn_t *dispatch_fns; + void **data; + struct timerlist timerlist; + pthread_mutex_t mutex; +}; +#define POLLINSTANCE_MUTEX_OFFSET offset_of(struct poll_instance, mutex) + +struct handle { + int valid; + void *instance; + unsigned int generation; +}; + +struct handle_database { + unsigned int handle_count; + struct handle *handles; + unsigned int generation; + pthread_mutex_t mutex; +}; + +#define offset_of(type,member) (int)(&(((type *)0)->member)) + +#define HANDLECONVERT_NOLOCKING 0x80000000 +#define HANDLECONVERT_DONTUNLOCKDB 0x40000000 + +int handle_create ( + struct handle_database *handle_database, + void **instance_out, + int instance_size, + int *handle_out) +{ + int handle; + void *new_handles; + int found = 0; + void *instance; + + pthread_mutex_lock (&handle_database->mutex); + + for (handle = 0; handle < handle_database->handle_count; handle++) { + if (handle_database->handles[handle].valid == 0) { + found = 1; + break; + } + } + if (found == 0) { + handle_database->handle_count += 1; + new_handles = (struct handle *)realloc (handle_database->handles, + sizeof (struct handle) * handle_database->handle_count); + if (new_handles == 0) { + pthread_mutex_unlock (&handle_database->mutex); + errno = ENOMEM; + return (-1); + } + handle_database->handles = new_handles; + } + instance = (void *)malloc (instance_size); + if (instance == 0) { + errno = ENOMEM; + return (-1); + } + memset (instance, 0, instance_size); + + handle_database->handles[handle].valid = 1; + handle_database->handles[handle].instance = instance; + handle_database->handles[handle].generation = handle_database->generation++; + + *handle_out = handle; + *instance_out = instance; + + pthread_mutex_unlock (&handle_database->mutex); + return (0); +} + +int handle_convert ( + struct handle_database *handle_database, + unsigned int handle, + void **instance, + int offset_to_mutex, + unsigned int *generation_out) +{ + int unlock_db; + int locking; + + unlock_db = (0 == (offset_to_mutex & HANDLECONVERT_DONTUNLOCKDB)); + locking = (0 == (offset_to_mutex & HANDLECONVERT_NOLOCKING)); + offset_to_mutex &= 0x00fffff; /* remove 8 bits of flags */ + + if (locking) { + pthread_mutex_lock (&handle_database->mutex); + } + +/* Add this later + res = saHandleVerify (handle_database, handle); + if (res == -1) { + if (locking) { + pthread_mutex_unlock (&handle_database->mutex); + } + errno = ENOENT; + return (-1); + } +*/ + + *instance = handle_database->handles[handle].instance; + if (generation_out) { + *generation_out = handle_database->handles[handle].generation; + } + + /* + * This function exits holding the mutex in the instance instance + * pointed to by offset_to_mutex (if NOLOCKING isn't set) + */ + if (locking) { + pthread_mutex_lock ((pthread_mutex_t *)(*instance + offset_to_mutex)); + if (unlock_db) { + pthread_mutex_unlock (&handle_database->mutex); + } + } + + return (0); +} + + +/* + * All instances in one database + */ +static struct handle_database poll_instance_database = { + handle_count: 0, + handles: 0, + generation: 0, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +poll_handle poll_create (void) +{ + poll_handle poll_handle; + struct poll_instance *poll_instance; + int res; + + res = handle_create (&poll_instance_database, (void *)&poll_instance, + sizeof (struct poll_instance), &poll_handle); + if (res == -1) { + goto error_exit; + } + poll_instance->ufds = 0; + poll_instance->nfds = 0; + poll_instance->dispatch_fns = 0; + poll_instance->data = 0; + timerlist_init (&poll_instance->timerlist); + + return (poll_handle); + +error_exit: + return (-1); +} + +int poll_destroy (poll_handle poll_handle) +{ + struct poll_instance *poll_instance; + int res; + + res = handle_convert (&poll_instance_database, poll_handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + if (res == -1) { + goto error_exit; + } + + if (poll_instance->ufds) { + free (poll_instance->ufds); + } + if (poll_instance->dispatch_fns) { + free (poll_instance->dispatch_fns); + } + if (poll_instance->data) { + free (poll_instance->data); + } + timerlist_free (&poll_instance->timerlist); +// TODO destroy poll + + return (0); + +error_exit: + return (-1); +} + +int poll_dispatch_add ( + poll_handle handle, + int fd, + int events, + void *data, + int (*dispatch_fn) (poll_handle poll_handle, int fd, int revents, void *data)) +{ + struct poll_instance *poll_instance; + struct pollfd *ufds; + dispatch_fn_t *dispatch_fns; + void **data_list; + int res; + int found = 0; + int install_pos; + + res = handle_convert (&poll_instance_database, handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + + if (res == -1) { + goto error_exit; + } + + for (found = 0, install_pos = 0; install_pos < poll_instance->nfds; install_pos++) { + if (poll_instance->ufds[install_pos].fd == -1) { + found = 1; + break; + } + } + + if (found == 0) { + /* + * Grow pollfd list + */ + ufds = (struct pollfd *)realloc (poll_instance->ufds, + (poll_instance->nfds + 1) * sizeof (struct pollfd)); + if (ufds == 0) { + errno = ENOMEM; + goto error_exit; + } + poll_instance->ufds = ufds; + + /* + * Grow dispatch functions list + */ + dispatch_fns = (dispatch_fn_t *)realloc (poll_instance->dispatch_fns, + (poll_instance->nfds + 1) * sizeof (dispatch_fn_t)); + if (dispatch_fns == 0) { + errno = ENOMEM; + goto error_exit; + } + poll_instance->dispatch_fns = dispatch_fns; + + /* + * Grow data list + */ + data_list = (void **)realloc (poll_instance->data, + (poll_instance->nfds + 1) * sizeof (void *)); + if (data_list == 0) { + errno = ENOMEM; + goto error_exit; + } + poll_instance->data = data_list; + + poll_instance->nfds += 1; + install_pos = poll_instance->nfds - 1; + } + + /* + * Install new dispatch handler + */ + poll_instance->ufds[install_pos].fd = fd; + poll_instance->ufds[install_pos].events = events; + poll_instance->ufds[install_pos].revents = 0; + poll_instance->dispatch_fns[install_pos] = dispatch_fn; + poll_instance->data[install_pos] = data; + + return (0); + +error_exit: + return (-1); +} + +int poll_dispatch_modify ( + poll_handle handle, + int fd, + int events, + int (*dispatch_fn) (poll_handle poll_handle, int fd, int revents, void *data)) +{ + struct poll_instance *poll_instance; + int i; + int res; + + res = handle_convert (&poll_instance_database, handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + if (res == -1) { + return (-1); + } + + /* + * Find file descriptor to modify events and dispatch function + */ + for (i = 0; i < poll_instance->nfds; i++) { + if (poll_instance->ufds[i].fd == fd) { + poll_instance->ufds[i].events = events; + poll_instance->dispatch_fns[i] = dispatch_fn; + return (0); + } + } + + errno = EBADF; + return (-1); +} + +int poll_dispatch_delete ( + poll_handle handle, + int fd) +{ + struct poll_instance *poll_instance; + int i; + int res; + int found = 0; + + res = handle_convert (&poll_instance_database, handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + if (res == -1) { + goto error_exit; + } + + /* + * Find dispatch fd to delete + */ + for (i = 0; i < poll_instance->nfds; i++) { + if (poll_instance->ufds[i].fd == fd) { + found = 1; + break; + } + } + + if (found) { + poll_instance->ufds[i].fd = -1; + return (0); + } + +error_exit: + errno = EBADF; + return (-1); +} + +int poll_timer_add ( + poll_handle handle, + int msec_in_future, void *data, + void (*timer_fn) (void *data), + poll_timer_handle *timer_handle_out) +{ + struct poll_instance *poll_instance; + poll_timer_handle timer_handle; + int res; + + res = handle_convert (&poll_instance_database, handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + if (res == -1) { + return (-1); + } + + timer_handle = (poll_timer_handle)timerlist_add_future (&poll_instance->timerlist, + timer_fn, data, msec_in_future); + + if (timer_handle != 0) { + *timer_handle_out = timer_handle; + return (0); + } + return (-1); +} + +int poll_timer_delete ( + poll_handle handle, + poll_timer_handle timer_handle) +{ + struct poll_instance *poll_instance; + int res; + + if (timer_handle == 0) { + return (0); + } + res = handle_convert (&poll_instance_database, handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + if (res == -1) { + return (-1); + } + + timerlist_del (&poll_instance->timerlist, (void *)timer_handle); + return (0); +} + +int poll_run ( + poll_handle handle) +{ + struct poll_instance *poll_instance; + int i; + int timeout = -1; + int res; + + res = handle_convert (&poll_instance_database, handle, + (void *)&poll_instance, POLLINSTANCE_MUTEX_OFFSET, 0); + if (res == -1) { + goto error_exit; + } + + for (;;) { + timeout = timerlist_timeout_msec (&poll_instance->timerlist); + +retry_poll: + res = poll (poll_instance->ufds, poll_instance->nfds, timeout); + if (errno == EINTR && res == -1) { + goto retry_poll; + } else + if (res == -1) { + goto error_exit; + } + + + for (i = 0; i < poll_instance->nfds; i++) { + if (poll_instance->ufds[i].fd != -1 && + poll_instance->ufds[i].revents) { + + res = poll_instance->dispatch_fns[i] (handle, poll_instance->ufds[i].fd, + poll_instance->ufds[i].revents, poll_instance->data[i]); + + /* + * Remove dispatch functions that return -1 + */ + if (res == -1) { + poll_instance->ufds[i].fd = -1; /* empty entry */ + } + } + } + timerlist_expire (&poll_instance->timerlist); + } /* for (;;) */ + +error_exit: + return (-1); +} + +int poll_stop ( + poll_handle handle); diff --git a/exec/poll.h b/exec/poll.h index e69de29b..875fdf0f 100644 --- a/exec/poll.h +++ b/exec/poll.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 + +typedef int poll_timer_handle; +typedef int poll_handle; + +poll_handle poll_create (void); + +int poll_destroy (poll_handle poll_handle); + +int poll_dispatch_add ( + poll_handle handle, + int fd, + int events, + void *data, + int (*dispatch_fn) (poll_handle handle, int fd, int revents, void *data)); + +int poll_dispatch_modify ( + poll_handle handle, + int fd, + int events, + int (*dispatch_fn) (poll_handle poll_handle, int fd, int revents, void *data)); + + +int poll_dispatch_delete ( + poll_handle handle, + int fd); + +int poll_timer_add ( + poll_handle handle, + int msec_in_future, void *data, + void (*timer_fn) (void *data), + poll_timer_handle *timer_handle_out); + +int poll_timer_delete ( + poll_handle handle, + poll_timer_handle timer_handle); + +int poll_run ( + poll_handle handle); + +int poll_stop ( + poll_handle handle); + +#endif /* POLL_H_DEFINED */ diff --git a/exec/print.c b/exec/print.c index e69de29b..76866f4e 100644 --- a/exec/print.c +++ b/exec/print.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include + +#include "print.h" +#include "parse.h" +#include "../include/ais_types.h" + +/* + * logging printf + */ +void +internal_log_printf (int level, char *string, ...) +{ + va_list ap; + char newstring[1024]; + + va_start(ap, string); + + sprintf (newstring, "L(%x): %s", level, string); + vfprintf(stderr, newstring, ap); + + va_end(ap); +} + +extern char *getSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + static char node_address[300]; + int pos; + + for (i = 0, pos = 0; i < nodeAddress->length; i++) { + pos += sprintf (&node_address[pos], "%d.", nodeAddress->value[i]); + } + return (node_address); +} + +void printSaClmClusterNodeT (char *description, SaClmClusterNodeT *clusterNode) { + log_printf (LOG_LEVEL_NOTICE, "Node Information for %s:\n", description); + + log_printf (LOG_LEVEL_NOTICE, "\tnode id is %x\n", (int)clusterNode->nodeId); + + log_printf (LOG_LEVEL_NOTICE, "\tnode address is %s\n", getSaClmNodeAddressT (&clusterNode->nodeAddress)); + + log_printf (LOG_LEVEL_NOTICE, "\tnode name is %s.\n", getSaNameT (&clusterNode->nodeName)); + + log_printf (LOG_LEVEL_NOTICE, "\tcluster name is %s.\n", getSaNameT (&clusterNode->clusterName)); + + log_printf (LOG_LEVEL_NOTICE, "\tMember is %d\n", clusterNode->member); + + log_printf (LOG_LEVEL_NOTICE, "\tTimestamp is %llx nanoseconds\n", clusterNode->bootTimestamp); +} + +char *getSaNameT (SaNameT *name) +{ + static char ret_name[300]; + + memset (ret_name, 0, sizeof (ret_name)); + if (name->length > 299) { + memcpy (ret_name, name->value, 299); + } else { + + memcpy (ret_name, name->value, name->length); + } + return (ret_name); +} + +void saAmfPrintGroups (void) +{ + struct list_head *AmfGroupList; + struct list_head *AmfUnitList; + struct list_head *AmfComponentList; + struct list_head *AmfProtectionGroupList; + struct saAmfGroup *saAmfGroup; + struct saAmfUnit *AmfUnit; + struct saAmfComponent *AmfComponent; + struct saAmfProtectionGroup *AmfProtectionGroup; + + for (AmfGroupList = saAmfGroupHead.next; + AmfGroupList != &saAmfGroupHead; + AmfGroupList = AmfGroupList->next) { + + saAmfGroup = list_entry (AmfGroupList, + struct saAmfGroup, saAmfGroupList); + + log_printf (LOG_LEVEL_DEBUG, "group {\n"); + log_printf (LOG_LEVEL_DEBUG, "\tname = ", getSaNameT (&saAmfGroup->name)); + log_printf (LOG_LEVEL_DEBUG, "\tmodel = %d\n", saAmfGroup->model); + log_printf (LOG_LEVEL_DEBUG, "\tactive-units = %d\n", (int)saAmfGroup->saAmfActiveUnitsDesired); + log_printf (LOG_LEVEL_DEBUG, "\tbackup-units = %d\n", (int)saAmfGroup->saAmfStandbyUnitsDesired); + + for (AmfUnitList = saAmfGroup->saAmfUnitHead.next; + AmfUnitList != &saAmfGroup->saAmfUnitHead; + AmfUnitList = AmfUnitList->next) { + + AmfUnit = list_entry (AmfUnitList, + struct saAmfUnit, saAmfUnitList); + + log_printf (LOG_LEVEL_DEBUG, "\tunit {\n"); + log_printf (LOG_LEVEL_DEBUG, "\t\tname = ", getSaNameT (&AmfUnit->name)); + + for (AmfComponentList = AmfUnit->saAmfComponentHead.next; + AmfComponentList != &AmfUnit->saAmfComponentHead; + AmfComponentList = AmfComponentList->next) { + + AmfComponent = list_entry (AmfComponentList, + struct saAmfComponent, saAmfComponentList); + log_printf (LOG_LEVEL_DEBUG, "\t\tcomponent {\n"); + log_printf (LOG_LEVEL_DEBUG, "\t\t\tname = ", getSaNameT (&AmfComponent->name)); + log_printf (LOG_LEVEL_DEBUG, "\t\t\tmodel = %d\n", AmfComponent->componentCapabilityModel); + log_printf (LOG_LEVEL_DEBUG, "\t\t}\n"); + } + log_printf (LOG_LEVEL_DEBUG, "\t}\n"); + } + + for (AmfProtectionGroupList = saAmfGroup->saAmfProtectionGroupHead.next; + AmfProtectionGroupList != &saAmfGroup->saAmfProtectionGroupHead; + AmfProtectionGroupList = AmfProtectionGroupList->next) { + + AmfProtectionGroup = list_entry (AmfProtectionGroupList, + struct saAmfProtectionGroup, saAmfProtectionGroupList); + + log_printf (LOG_LEVEL_DEBUG, "\tprotection {\n"); + log_printf (LOG_LEVEL_DEBUG, "\t\tname = ", getSaNameT (&AmfProtectionGroup->name)); + + for (AmfComponentList = AmfProtectionGroup->saAmfMembersHead.next; + AmfComponentList != &AmfProtectionGroup->saAmfMembersHead; + AmfComponentList = AmfComponentList->next) { + + AmfComponent = list_entry (AmfComponentList, + struct saAmfComponent, saAmfProtectionGroupList); + + log_printf (LOG_LEVEL_DEBUG, "\t\tmember = ", getSaNameT (&AmfComponent->name)); + } + log_printf (LOG_LEVEL_DEBUG, "\t}\n"); + } + log_printf (LOG_LEVEL_DEBUG, "}\n"); + } +} diff --git a/exec/print.h b/exec/print.h index e69de29b..1ad30051 100644 --- a/exec/print.h +++ b/exec/print.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 PRINT_H_DEFINED +#define PRINT_H_DEFINED + +#include "../include/ais_types.h" + + +#define LOG_LEVEL_SECURITY 1 +#define LOG_LEVEL_ERROR 2 +#define LOG_LEVEL_WARNING 3 +#define LOG_LEVEL_NOTICE 4 +#define LOG_LEVEL_DEBUG 5 + +extern void internal_log_printf (int level, char *string, ...); + +/* + * The optimizer will remove DEBUG logging messages in production builds + */ +#ifdef DEBUG +#define log_printf(level,format,args...) { internal_log_printf (level,format,##args); } +#else +#define log_printf(level,format,args...) { if (level != LOG_LEVEL_DEBUG) internal_log_printf (level,format,##args); } +#endif + +extern char *getSaNameT (SaNameT *name); + +extern char *getSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress); + +extern void printSaClmClusterNodeT (char *description, SaClmClusterNodeT *clusterNode); + +extern void saAmfPrintGroups (void); + +#endif /* PRINT_H_DEFINED */ diff --git a/exec/profile b/exec/profile index e69de29b..dfb663b4 100644 --- a/exec/profile +++ b/exec/profile @@ -0,0 +1,560 @@ +Flat profile: + +Each sample counts as 0.01 seconds. + % cumulative self self total + time seconds seconds calls ms/call ms/call name + 21.95 0.09 0.09 274959 0.00 0.00 message_handler_mcast + 19.51 0.17 0.08 274977 0.00 0.00 pending_queues_deliver + 9.76 0.21 0.04 1655 0.02 0.05 user_deliver + 9.76 0.25 0.04 1 40.00 409.61 poll_run + 7.32 0.28 0.03 322067 0.00 0.00 timerlist_expire + 7.32 0.31 0.03 1623 0.02 0.03 deliver_fn + 4.88 0.33 0.02 322068 0.00 0.00 timerlist_timeout_msec + 4.88 0.35 0.02 322046 0.00 0.00 recv_handler + 2.44 0.36 0.01 47021 0.00 0.00 timerlist_add_future + 2.44 0.37 0.01 46913 0.00 0.00 message_handler_orf_token + 2.44 0.38 0.01 46913 0.00 0.00 orf_token_mcast + 2.44 0.39 0.01 46878 0.00 0.00 messages_free + 2.44 0.40 0.01 1632 0.01 0.01 SaNameTisNameT + 2.44 0.41 0.01 1527 0.01 0.01 message_handler_req_exec_ckpt_sectionwrite + 0.00 0.41 0.00 47304 0.00 0.00 poll_timer_delete + 0.00 0.41 0.00 47021 0.00 0.00 poll_timer_add + 0.00 0.41 0.00 47021 0.00 0.00 timerlist_add + 0.00 0.41 0.00 47019 0.00 0.00 timerlist_del + 0.00 0.41 0.00 46913 0.00 0.00 orf_token_evs + 0.00 0.41 0.00 46913 0.00 0.00 orf_token_rtr + 0.00 0.41 0.00 46878 0.00 0.00 sq_items_release + 0.00 0.41 0.00 1655 0.00 0.00 pend_delv_next_delivery_find + 0.00 0.41 0.00 1623 0.00 0.00 queue_reinit + 0.00 0.41 0.00 726 0.00 0.00 internal_log_printf + 0.00 0.41 0.00 125 0.00 0.00 mempool_free + 0.00 0.41 0.00 125 0.00 0.00 mempool_strdup + 0.00 0.41 0.00 125 0.00 0.00 strstr_rs + 0.00 0.41 0.00 71 0.00 0.00 ckptConfChg + 0.00 0.41 0.00 71 0.00 0.00 clmConfChg + 0.00 0.41 0.00 71 0.00 0.00 confchg_fn + 0.00 0.41 0.00 71 0.00 0.00 libraryNotificationLeave + 0.00 0.41 0.00 70 0.00 0.00 message_handler_memb_form_token + 0.00 0.41 0.00 53 0.00 0.00 message_handler_req_exec_clm_nodejoin + 0.00 0.41 0.00 52 0.00 0.00 message_handler_memb_attempt_join + 0.00 0.41 0.00 52 0.00 0.00 message_handler_memb_join + 0.00 0.41 0.00 41 0.00 0.01 message_handler_req_exec_ckpt_checkpointopen + 0.00 0.41 0.00 36 0.00 0.00 SaNameTisEqual + 0.00 0.41 0.00 35 0.00 0.00 memb_form_token_conf_desc_build + 0.00 0.41 0.00 35 0.00 0.00 queues_pend_delv_memb_new + 0.00 0.41 0.00 35 0.00 0.00 sq_reinit + 0.00 0.41 0.00 20 0.00 0.00 queue_init + 0.00 0.41 0.00 19 0.00 0.00 memb_state_commit_enter + 0.00 0.41 0.00 19 0.00 0.00 memb_state_gather_enter + 0.00 0.41 0.00 18 0.00 0.02 findComponent + 0.00 0.41 0.00 18 0.00 0.00 gmi_mcast + 0.00 0.41 0.00 18 0.00 0.00 gmi_pend_trans_item_store + 0.00 0.41 0.00 18 0.00 0.00 libraryNotificationJoin + 0.00 0.41 0.00 18 0.00 0.00 memb_print_commit_set + 0.00 0.41 0.00 18 0.00 0.00 memb_state_commit_consensus + 0.00 0.41 0.00 15 0.00 0.00 orf_timer_function_token_timeout + 0.00 0.41 0.00 12 0.00 0.00 mempool_malloc + 0.00 0.41 0.00 5 0.00 0.00 memb_timer_function_state_gather + 0.00 0.41 0.00 2 0.00 0.01 message_handler_req_exec_ckpt_sectioncreate + 0.00 0.41 0.00 2 0.00 0.00 poll_dispatch_add + 0.00 0.41 0.00 1 0.00 0.00 aisexec_libais_bind + 0.00 0.41 0.00 1 0.00 0.00 amfExecutiveInitialize + 0.00 0.41 0.00 1 0.00 0.39 amfReadGroups + 0.00 0.41 0.00 1 0.00 0.00 clmExecutiveInitialize + 0.00 0.41 0.00 1 0.00 0.00 determine_local_if + 0.00 0.41 0.00 1 0.00 0.00 gmi_init + 0.00 0.41 0.00 1 0.00 0.00 gmi_join + 0.00 0.41 0.00 1 0.00 0.00 grow_connections_table + 0.00 0.41 0.00 1 0.00 0.00 handle_create + 0.00 0.41 0.00 1 0.00 0.00 memb_conf_id_build + 0.00 0.41 0.00 1 0.00 0.00 memb_timer_function_state_commit_timeout + 0.00 0.41 0.00 1 0.00 0.00 mempool_init + 0.00 0.41 0.00 1 0.00 0.00 mempool_realloc + 0.00 0.41 0.00 1 0.00 0.00 poll_create + 0.00 0.41 0.00 1 0.00 0.00 sq_init + 0.00 0.41 0.00 1 0.00 0.00 this_ip_set + 0.00 0.41 0.00 1 0.00 0.00 timerlist_init + + % the percentage of the total running time of the +time program used by this function. + +cumulative a running sum of the number of seconds accounted + seconds for by this function and those listed above it. + + self the number of seconds accounted for by this +seconds function alone. This is the major sort for this + listing. + +calls the number of times this function was invoked, if + this function is profiled, else blank. + + self the average number of milliseconds spent in this +ms/call function per call, if this function is profiled, + else blank. + + total the average number of milliseconds spent in this +ms/call function and its descendents per call, if this + function is profiled, else blank. + +name the name of the function. This is the minor sort + for this listing. The index shows the location of + the function in the gprof listing. If the index is + in parenthesis it shows where it would appear in + the gprof listing if it were to be printed. + + Call graph (explanation follows) + + +granularity: each sample hit covers 4 byte(s) for 2.44% of 0.41 seconds + +index % time self children called name + +[1] 100.0 0.00 0.41 main [1] + 0.04 0.37 1/1 poll_run [2] + 0.00 0.00 1/1 amfReadGroups [18] + 0.00 0.00 1/1 gmi_init [27] + 0.00 0.00 2/726 internal_log_printf [36] + 0.00 0.00 1/1 poll_create [69] + 0.00 0.00 1/1 mempool_init [67] + 0.00 0.00 1/1 aisexec_libais_bind [58] + 0.00 0.00 1/1 grow_connections_table [63] + 0.00 0.00 1/2 poll_dispatch_add [57] + 0.00 0.00 1/1 gmi_join [62] + 0.00 0.00 1/1 amfExecutiveInitialize [59] + 0.00 0.00 1/1 clmExecutiveInitialize [60] +----------------------------------------------- + 0.04 0.37 1/1 main [1] +[2] 99.9 0.04 0.37 1 poll_run [2] + 0.02 0.30 322046/322046 recv_handler [3] + 0.03 0.00 322067/322067 timerlist_expire [9] + 0.02 0.00 322068/322068 timerlist_timeout_msec [10] +----------------------------------------------- + 0.02 0.30 322046/322046 poll_run [2] +[3] 78.0 0.02 0.30 322046 recv_handler [3] + 0.09 0.17 274959/274959 message_handler_mcast [4] + 0.01 0.03 46913/46913 message_handler_orf_token [8] + 0.00 0.00 70/70 message_handler_memb_form_token [20] + 0.00 0.00 52/52 message_handler_memb_join [24] + 0.00 0.00 52/52 message_handler_memb_attempt_join [26] +----------------------------------------------- + 0.09 0.17 274959/274959 recv_handler [3] +[4] 63.3 0.09 0.17 274959 message_handler_mcast [4] + 0.08 0.09 274959/274977 pending_queues_deliver [5] +----------------------------------------------- + 0.00 0.00 18/274977 orf_token_mcast [12] + 0.08 0.09 274959/274977 message_handler_mcast [4] +[5] 41.4 0.08 0.09 274977 pending_queues_deliver [5] + 0.04 0.05 1655/1655 user_deliver [6] +----------------------------------------------- + 0.04 0.05 1655/1655 pending_queues_deliver [5] +[6] 21.9 0.04 0.05 1655 user_deliver [6] + 0.03 0.02 1623/1623 deliver_fn [7] + 0.00 0.00 1655/1655 pend_delv_next_delivery_find [34] + 0.00 0.00 1623/1623 queue_reinit [35] +----------------------------------------------- + 0.03 0.02 1623/1623 user_deliver [6] +[7] 12.1 0.03 0.02 1623 deliver_fn [7] + 0.01 0.01 1527/1527 message_handler_req_exec_ckpt_sectionwrite [11] + 0.00 0.00 41/41 message_handler_req_exec_ckpt_checkpointopen [19] + 0.00 0.00 2/2 message_handler_req_exec_ckpt_sectioncreate [21] + 0.00 0.00 53/53 message_handler_req_exec_clm_nodejoin [44] +----------------------------------------------- + 0.01 0.03 46913/46913 recv_handler [3] +[8] 9.8 0.01 0.03 46913 message_handler_orf_token [8] + 0.01 0.00 46913/46913 orf_token_mcast [12] + 0.01 0.00 46878/46878 messages_free [15] + 0.00 0.01 46913/47021 poll_timer_add [13] + 0.00 0.00 46913/46913 orf_token_rtr [32] + 0.00 0.00 46913/46913 orf_token_evs [31] + 0.00 0.00 46913/47304 poll_timer_delete [28] +----------------------------------------------- + 0.03 0.00 322067/322067 poll_run [2] +[9] 7.3 0.03 0.00 322067 timerlist_expire [9] + 0.00 0.00 15/19 memb_state_gather_enter [23] + 0.00 0.00 5/5 memb_timer_function_state_gather [25] + 0.00 0.00 15/15 orf_timer_function_token_timeout [55] + 0.00 0.00 1/1 memb_timer_function_state_commit_timeout [66] +----------------------------------------------- + 0.02 0.00 322068/322068 poll_run [2] +[10] 4.9 0.02 0.00 322068 timerlist_timeout_msec [10] +----------------------------------------------- + 0.01 0.01 1527/1527 deliver_fn [7] +[11] 4.7 0.01 0.01 1527 message_handler_req_exec_ckpt_sectionwrite [11] + 0.01 0.00 1527/1632 SaNameTisNameT [16] +----------------------------------------------- + 0.01 0.00 46913/46913 message_handler_orf_token [8] +[12] 2.4 0.01 0.00 46913 orf_token_mcast [12] + 0.00 0.00 18/274977 pending_queues_deliver [5] +----------------------------------------------- + 0.00 0.00 19/47021 memb_state_commit_enter [22] + 0.00 0.00 19/47021 memb_state_gather_enter [23] + 0.00 0.00 70/47021 message_handler_memb_form_token [20] + 0.00 0.01 46913/47021 message_handler_orf_token [8] +[13] 2.4 0.00 0.01 47021 poll_timer_add [13] + 0.01 0.00 47021/47021 timerlist_add_future [14] +----------------------------------------------- + 0.01 0.00 47021/47021 poll_timer_add [13] +[14] 2.4 0.01 0.00 47021 timerlist_add_future [14] + 0.00 0.00 47021/47021 timerlist_add [29] +----------------------------------------------- + 0.01 0.00 46878/46878 message_handler_orf_token [8] +[15] 2.4 0.01 0.00 46878 messages_free [15] + 0.00 0.00 46878/46878 sq_items_release [33] +----------------------------------------------- + 0.00 0.00 2/1632 message_handler_req_exec_ckpt_sectioncreate [21] + 0.00 0.00 40/1632 message_handler_req_exec_ckpt_checkpointopen [19] + 0.00 0.00 63/1632 findComponent [17] + 0.01 0.00 1527/1632 message_handler_req_exec_ckpt_sectionwrite [11] +[16] 2.4 0.01 0.00 1632 SaNameTisNameT [16] +----------------------------------------------- + 0.00 0.00 18/18 amfReadGroups [18] +[17] 0.1 0.00 0.00 18 findComponent [17] + 0.00 0.00 63/1632 SaNameTisNameT [16] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[18] 0.1 0.00 0.00 1 amfReadGroups [18] + 0.00 0.00 18/18 findComponent [17] + 0.00 0.00 125/125 strstr_rs [39] + 0.00 0.00 36/36 SaNameTisEqual [45] + 0.00 0.00 12/12 mempool_malloc [56] +----------------------------------------------- + 0.00 0.00 41/41 deliver_fn [7] +[19] 0.1 0.00 0.00 41 message_handler_req_exec_ckpt_checkpointopen [19] + 0.00 0.00 40/1632 SaNameTisNameT [16] +----------------------------------------------- + 0.00 0.00 70/70 recv_handler [3] +[20] 0.0 0.00 0.00 70 message_handler_memb_form_token [20] + 0.00 0.00 70/47021 poll_timer_add [13] + 0.00 0.00 280/47304 poll_timer_delete [28] + 0.00 0.00 35/35 memb_form_token_conf_desc_build [46] +----------------------------------------------- + 0.00 0.00 2/2 deliver_fn [7] +[21] 0.0 0.00 0.00 2 message_handler_req_exec_ckpt_sectioncreate [21] + 0.00 0.00 2/1632 SaNameTisNameT [16] +----------------------------------------------- + 0.00 0.00 5/19 memb_timer_function_state_gather [25] + 0.00 0.00 14/19 message_handler_memb_join [24] +[22] 0.0 0.00 0.00 19 memb_state_commit_enter [22] + 0.00 0.00 19/47021 poll_timer_add [13] + 0.00 0.00 19/47304 poll_timer_delete [28] +----------------------------------------------- + 0.00 0.00 1/19 gmi_init [27] + 0.00 0.00 3/19 message_handler_memb_attempt_join [26] + 0.00 0.00 15/19 timerlist_expire [9] +[23] 0.0 0.00 0.00 19 memb_state_gather_enter [23] + 0.00 0.00 19/47021 poll_timer_add [13] + 0.00 0.00 38/726 internal_log_printf [36] + 0.00 0.00 19/47304 poll_timer_delete [28] +----------------------------------------------- + 0.00 0.00 52/52 recv_handler [3] +[24] 0.0 0.00 0.00 52 message_handler_memb_join [24] + 0.00 0.00 14/19 memb_state_commit_enter [22] + 0.00 0.00 18/18 memb_print_commit_set [53] + 0.00 0.00 18/18 memb_state_commit_consensus [54] + 0.00 0.00 18/726 internal_log_printf [36] +----------------------------------------------- + 0.00 0.00 5/5 timerlist_expire [9] +[25] 0.0 0.00 0.00 5 memb_timer_function_state_gather [25] + 0.00 0.00 5/19 memb_state_commit_enter [22] +----------------------------------------------- + 0.00 0.00 52/52 recv_handler [3] +[26] 0.0 0.00 0.00 52 message_handler_memb_attempt_join [26] + 0.00 0.00 3/19 memb_state_gather_enter [23] + 0.00 0.00 86/726 internal_log_printf [36] + 0.00 0.00 3/47304 poll_timer_delete [28] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[27] 0.0 0.00 0.00 1 gmi_init [27] + 0.00 0.00 1/19 memb_state_gather_enter [23] + 0.00 0.00 1/20 queue_init [49] + 0.00 0.00 1/1 sq_init [70] + 0.00 0.00 1/1 determine_local_if [61] + 0.00 0.00 1/1 memb_conf_id_build [65] + 0.00 0.00 1/2 poll_dispatch_add [57] +----------------------------------------------- + 0.00 0.00 3/47304 message_handler_memb_attempt_join [26] + 0.00 0.00 19/47304 memb_state_commit_enter [22] + 0.00 0.00 19/47304 memb_state_gather_enter [23] + 0.00 0.00 70/47304 orf_token_evs [31] + 0.00 0.00 280/47304 message_handler_memb_form_token [20] + 0.00 0.00 46913/47304 message_handler_orf_token [8] +[28] 0.0 0.00 0.00 47304 poll_timer_delete [28] + 0.00 0.00 47019/47019 timerlist_del [30] +----------------------------------------------- + 0.00 0.00 47021/47021 timerlist_add_future [14] +[29] 0.0 0.00 0.00 47021 timerlist_add [29] +----------------------------------------------- + 0.00 0.00 47019/47019 poll_timer_delete [28] +[30] 0.0 0.00 0.00 47019 timerlist_del [30] +----------------------------------------------- + 0.00 0.00 46913/46913 message_handler_orf_token [8] +[31] 0.0 0.00 0.00 46913 orf_token_evs [31] + 0.00 0.00 70/47304 poll_timer_delete [28] + 0.00 0.00 70/71 confchg_fn [42] + 0.00 0.00 35/726 internal_log_printf [36] + 0.00 0.00 35/35 sq_reinit [48] + 0.00 0.00 35/35 queues_pend_delv_memb_new [47] +----------------------------------------------- + 0.00 0.00 46913/46913 message_handler_orf_token [8] +[32] 0.0 0.00 0.00 46913 orf_token_rtr [32] +----------------------------------------------- + 0.00 0.00 46878/46878 messages_free [15] +[33] 0.0 0.00 0.00 46878 sq_items_release [33] +----------------------------------------------- + 0.00 0.00 1655/1655 user_deliver [6] +[34] 0.0 0.00 0.00 1655 pend_delv_next_delivery_find [34] +----------------------------------------------- + 0.00 0.00 1623/1623 user_deliver [6] +[35] 0.0 0.00 0.00 1623 queue_reinit [35] +----------------------------------------------- + 0.00 0.00 1/726 sigintr_handler [175] + 0.00 0.00 1/726 memb_timer_function_state_commit_timeout [66] + 0.00 0.00 2/726 main [1] + 0.00 0.00 15/726 orf_timer_function_token_timeout [55] + 0.00 0.00 18/726 message_handler_memb_join [24] + 0.00 0.00 35/726 orf_token_evs [31] + 0.00 0.00 38/726 memb_state_gather_enter [23] + 0.00 0.00 53/726 message_handler_req_exec_clm_nodejoin [44] + 0.00 0.00 86/726 message_handler_memb_attempt_join [26] + 0.00 0.00 477/726 clmConfChg [41] +[36] 0.0 0.00 0.00 726 internal_log_printf [36] +----------------------------------------------- + 0.00 0.00 125/125 strstr_rs [39] +[37] 0.0 0.00 0.00 125 mempool_free [37] +----------------------------------------------- + 0.00 0.00 125/125 strstr_rs [39] +[38] 0.0 0.00 0.00 125 mempool_strdup [38] +----------------------------------------------- + 0.00 0.00 125/125 amfReadGroups [18] +[39] 0.0 0.00 0.00 125 strstr_rs [39] + 0.00 0.00 125/125 mempool_strdup [38] + 0.00 0.00 125/125 mempool_free [37] +----------------------------------------------- + 0.00 0.00 71/71 confchg_fn [42] +[40] 0.0 0.00 0.00 71 ckptConfChg [40] +----------------------------------------------- + 0.00 0.00 71/71 confchg_fn [42] +[41] 0.0 0.00 0.00 71 clmConfChg [41] + 0.00 0.00 477/726 internal_log_printf [36] + 0.00 0.00 71/71 libraryNotificationLeave [43] + 0.00 0.00 18/18 gmi_mcast [50] +----------------------------------------------- + 0.00 0.00 1/71 memb_timer_function_state_commit_timeout [66] + 0.00 0.00 70/71 orf_token_evs [31] +[42] 0.0 0.00 0.00 71 confchg_fn [42] + 0.00 0.00 71/71 ckptConfChg [40] + 0.00 0.00 71/71 clmConfChg [41] +----------------------------------------------- + 0.00 0.00 71/71 clmConfChg [41] +[43] 0.0 0.00 0.00 71 libraryNotificationLeave [43] +----------------------------------------------- + 0.00 0.00 53/53 deliver_fn [7] +[44] 0.0 0.00 0.00 53 message_handler_req_exec_clm_nodejoin [44] + 0.00 0.00 53/726 internal_log_printf [36] + 0.00 0.00 18/18 libraryNotificationJoin [52] +----------------------------------------------- + 0.00 0.00 36/36 amfReadGroups [18] +[45] 0.0 0.00 0.00 36 SaNameTisEqual [45] +----------------------------------------------- + 0.00 0.00 35/35 message_handler_memb_form_token [20] +[46] 0.0 0.00 0.00 35 memb_form_token_conf_desc_build [46] +----------------------------------------------- + 0.00 0.00 35/35 orf_token_evs [31] +[47] 0.0 0.00 0.00 35 queues_pend_delv_memb_new [47] + 0.00 0.00 19/20 queue_init [49] +----------------------------------------------- + 0.00 0.00 35/35 orf_token_evs [31] +[48] 0.0 0.00 0.00 35 sq_reinit [48] +----------------------------------------------- + 0.00 0.00 1/20 gmi_init [27] + 0.00 0.00 19/20 queues_pend_delv_memb_new [47] +[49] 0.0 0.00 0.00 20 queue_init [49] +----------------------------------------------- + 0.00 0.00 18/18 clmConfChg [41] +[50] 0.0 0.00 0.00 18 gmi_mcast [50] + 0.00 0.00 18/18 gmi_pend_trans_item_store [51] +----------------------------------------------- + 0.00 0.00 18/18 gmi_mcast [50] +[51] 0.0 0.00 0.00 18 gmi_pend_trans_item_store [51] +----------------------------------------------- + 0.00 0.00 18/18 message_handler_req_exec_clm_nodejoin [44] +[52] 0.0 0.00 0.00 18 libraryNotificationJoin [52] +----------------------------------------------- + 0.00 0.00 18/18 message_handler_memb_join [24] +[53] 0.0 0.00 0.00 18 memb_print_commit_set [53] +----------------------------------------------- + 0.00 0.00 18/18 message_handler_memb_join [24] +[54] 0.0 0.00 0.00 18 memb_state_commit_consensus [54] +----------------------------------------------- + 0.00 0.00 15/15 timerlist_expire [9] +[55] 0.0 0.00 0.00 15 orf_timer_function_token_timeout [55] + 0.00 0.00 15/726 internal_log_printf [36] +----------------------------------------------- + 0.00 0.00 12/12 amfReadGroups [18] +[56] 0.0 0.00 0.00 12 mempool_malloc [56] +----------------------------------------------- + 0.00 0.00 1/2 main [1] + 0.00 0.00 1/2 gmi_init [27] +[57] 0.0 0.00 0.00 2 poll_dispatch_add [57] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[58] 0.0 0.00 0.00 1 aisexec_libais_bind [58] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[59] 0.0 0.00 0.00 1 amfExecutiveInitialize [59] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[60] 0.0 0.00 0.00 1 clmExecutiveInitialize [60] + 0.00 0.00 1/1 this_ip_set [71] +----------------------------------------------- + 0.00 0.00 1/1 gmi_init [27] +[61] 0.0 0.00 0.00 1 determine_local_if [61] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[62] 0.0 0.00 0.00 1 gmi_join [62] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[63] 0.0 0.00 0.00 1 grow_connections_table [63] + 0.00 0.00 1/1 mempool_realloc [68] +----------------------------------------------- + 0.00 0.00 1/1 poll_create [69] +[64] 0.0 0.00 0.00 1 handle_create [64] +----------------------------------------------- + 0.00 0.00 1/1 gmi_init [27] +[65] 0.0 0.00 0.00 1 memb_conf_id_build [65] +----------------------------------------------- + 0.00 0.00 1/1 timerlist_expire [9] +[66] 0.0 0.00 0.00 1 memb_timer_function_state_commit_timeout [66] + 0.00 0.00 1/726 internal_log_printf [36] + 0.00 0.00 1/71 confchg_fn [42] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[67] 0.0 0.00 0.00 1 mempool_init [67] +----------------------------------------------- + 0.00 0.00 1/1 grow_connections_table [63] +[68] 0.0 0.00 0.00 1 mempool_realloc [68] +----------------------------------------------- + 0.00 0.00 1/1 main [1] +[69] 0.0 0.00 0.00 1 poll_create [69] + 0.00 0.00 1/1 handle_create [64] + 0.00 0.00 1/1 timerlist_init [72] +----------------------------------------------- + 0.00 0.00 1/1 gmi_init [27] +[70] 0.0 0.00 0.00 1 sq_init [70] +----------------------------------------------- + 0.00 0.00 1/1 clmExecutiveInitialize [60] +[71] 0.0 0.00 0.00 1 this_ip_set [71] +----------------------------------------------- + 0.00 0.00 1/1 poll_create [69] +[72] 0.0 0.00 0.00 1 timerlist_init [72] +----------------------------------------------- + + This table describes the call tree of the program, and was sorted by + the total amount of time spent in each function and its children. + + Each entry in this table consists of several lines. The line with the + index number at the left hand margin lists the current function. + The lines above it list the functions that called this function, + and the lines below it list the functions this one called. + This line lists: + index A unique number given to each element of the table. + Index numbers are sorted numerically. + The index number is printed next to every function name so + it is easier to look up where the function in the table. + + % time This is the percentage of the `total' time that was spent + in this function and its children. Note that due to + different viewpoints, functions excluded by options, etc, + these numbers will NOT add up to 100%. + + self This is the total amount of time spent in this function. + + children This is the total amount of time propagated into this + function by its children. + + called This is the number of times the function was called. + If the function called itself recursively, the number + only includes non-recursive calls, and is followed by + a `+' and the number of recursive calls. + + name The name of the current function. The index number is + printed after it. If the function is a member of a + cycle, the cycle number is printed between the + function's name and the index number. + + + For the function's parents, the fields have the following meanings: + + self This is the amount of time that was propagated directly + from the function into this parent. + + children This is the amount of time that was propagated from + the function's children into this parent. + + called This is the number of times this parent called the + function `/' the total number of times the function + was called. Recursive calls to the function are not + included in the number after the `/'. + + name This is the name of the parent. The parent's index + number is printed after it. If the parent is a + member of a cycle, the cycle number is printed between + the name and the index number. + + If the parents of the function cannot be determined, the word + `' is printed in the `name' field, and all the other + fields are blank. + + For the function's children, the fields have the following meanings: + + self This is the amount of time that was propagated directly + from the child into the function. + + children This is the amount of time that was propagated from the + child's children to the function. + + called This is the number of times the function called + this child `/' the total number of times the child + was called. Recursive calls by the child are not + listed in the number after the `/'. + + name This is the name of the child. The child's index + number is printed after it. If the child is a + member of a cycle, the cycle number is printed + between the name and the index number. + + If there are any cycles (circles) in the call graph, there is an + entry for the cycle-as-a-whole. This entry shows who called the + cycle (as parents) and the members of the cycle (as children.) + The `+' recursive calls entry shows the number of function calls that + were internal to the cycle, and the calls entry for each member shows, + for that member, how many times it was called from other members of + the cycle. + + +Index by function name + + [45] SaNameTisEqual [54] memb_state_commit_consensus [34] pend_delv_next_delivery_find + [16] SaNameTisNameT [22] memb_state_commit_enter [5] pending_queues_deliver + [58] aisexec_libais_bind [23] memb_state_gather_enter [69] poll_create + [59] amfExecutiveInitialize [66] memb_timer_function_state_commit_timeout [57] poll_dispatch_add + [18] amfReadGroups [25] memb_timer_function_state_gather [2] poll_run + [40] ckptConfChg [37] mempool_free [13] poll_timer_add + [41] clmConfChg [67] mempool_init [28] poll_timer_delete + [60] clmExecutiveInitialize [56] mempool_malloc [49] queue_init + [42] confchg_fn [68] mempool_realloc [35] queue_reinit + [7] deliver_fn [38] mempool_strdup [47] queues_pend_delv_memb_new + [61] determine_local_if [4] message_handler_mcast [3] recv_handler + [17] findComponent [26] message_handler_memb_attempt_join [70] sq_init + [27] gmi_init [20] message_handler_memb_form_token [33] sq_items_release + [62] gmi_join [24] message_handler_memb_join [48] sq_reinit + [50] gmi_mcast [8] message_handler_orf_token [39] strstr_rs + [51] gmi_pend_trans_item_store [19] message_handler_req_exec_ckpt_checkpointopen [71] this_ip_set + [63] grow_connections_table [21] message_handler_req_exec_ckpt_sectioncreate [29] timerlist_add + [64] handle_create [11] message_handler_req_exec_ckpt_sectionwrite [14] timerlist_add_future + [36] internal_log_printf [44] message_handler_req_exec_clm_nodejoin [30] timerlist_del + [52] libraryNotificationJoin [15] messages_free [9] timerlist_expire + [43] libraryNotificationLeave [55] orf_timer_function_token_timeout [72] timerlist_init + [65] memb_conf_id_build [31] orf_token_evs [10] timerlist_timeout_msec + [46] memb_form_token_conf_desc_build [12] orf_token_mcast [6] user_deliver + [53] memb_print_commit_set [32] orf_token_rtr diff --git a/exec/tlist.c b/exec/tlist.c index e69de29b..d72d42ff 100644 --- a/exec/tlist.c +++ b/exec/tlist.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include + +#include "../include/list.h" +#include "tlist.h" + +struct timer { + struct list_head list; + struct timeval tv; + void (*timer_fn)(void *data); + void *data; +}; + +void timerlist_init (struct timerlist *timerlist) +{ + list_init (&timerlist->timer_head); +} + +void timerlist_free (struct timerlist *timerlist) +{ +} + +int timers_inuse = 0; + +static inline void timeval_adjust_to_msec (struct timeval *tv) { + tv->tv_usec = (tv->tv_usec / 1000) * 1000; +} + + +void timerlist_add (struct timerlist *timerlist, struct timer *timer) +{ + struct list_head *timer_list = 0; + struct timer *timer_from_list; + int found; + + timeval_adjust_to_msec (&timer->tv); + 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 timer, list); + + if ((timer_from_list->tv.tv_sec > timer->tv.tv_sec) || + ((timer_from_list->tv.tv_sec == timer->tv.tv_sec) && + (timer_from_list->tv.tv_usec > timer->tv.tv_usec))) { + list_add (&timer->list, timer_list->prev); + found = 1; + break; /* for timer iteration */ + } + } + if (found == 0) { + list_add (&timer->list, timerlist->timer_head.prev); + timers_inuse++; + } +} + +timer_handle timerlist_add_future (struct timerlist *timerlist, + void (*timer_fn) (void *data), + void *data, + int msec_in_future) +{ + struct timer *timer; + struct timeval current_time; + int seconds; + int mseconds; + + timer = (struct timer *)malloc (sizeof (struct timer)); + if (timer == 0) { + errno = ENOMEM; + return (0); + } + + seconds = msec_in_future / 1000; + mseconds = msec_in_future % 1000; + + gettimeofday (¤t_time, 0); + timeval_adjust_to_msec (¤t_time); + timer->tv.tv_sec = current_time.tv_sec + seconds; + timer->tv.tv_usec = current_time.tv_usec + mseconds * 1000; + if (timer->tv.tv_usec >= 1000000) { + timer->tv.tv_sec++; + timer->tv.tv_usec -= 1000000; + } + timer->data = data; + timer->timer_fn = timer_fn; + timerlist_add (timerlist, timer); + + return (timer); +} + +void timerlist_del (struct timerlist *timerlist, timer_handle timer_handle) +{ + struct timer *timer = (struct timer *)timer_handle; + + list_del (&timer->list); + free (timer); + timers_inuse--; +} + +int timer_expire_get_tv (struct timerlist *timerlist, struct timeval *tv) +{ + struct timeval current_time; + struct timer *timer_from_list; + + /* + * empty list, no expire + */ + if (timerlist->timer_head.next == &timerlist->timer_head) { + return (-1); + } + + timer_from_list = list_entry (timerlist->timer_head.next, + struct timer, list); + + gettimeofday (¤t_time, 0); + timeval_adjust_to_msec (¤t_time); + + /* + * timer at head of list is expired, zero msecs required + */ + if ((timer_from_list->tv.tv_sec < current_time.tv_sec) || + ((timer_from_list->tv.tv_sec == current_time.tv_sec) && + (timer_from_list->tv.tv_usec <= current_time.tv_usec))) { + + tv->tv_sec = 0; + tv->tv_usec = 0; + } + + tv->tv_sec = timer_from_list->tv.tv_sec - current_time.tv_sec; + tv->tv_usec = timer_from_list->tv.tv_usec - current_time.tv_usec; + if (tv->tv_usec < 0) { + tv->tv_sec -= 1; + tv->tv_usec += 1000000; + } + if (tv->tv_sec < 0) { + tv->tv_sec = 0; + tv->tv_usec = 0; + } + + timeval_adjust_to_msec (tv); + return (0); +} + +int timerlist_timeout_msec (struct timerlist *timerlist) +{ + struct timeval current_time; + struct timer *timer_from_list; + int time_in_msec; + + /* + * empty list, no expire + */ + if (timerlist->timer_head.next == &timerlist->timer_head) { + return (-1); + } + + timer_from_list = list_entry (timerlist->timer_head.next, + struct timer, list); + + gettimeofday (¤t_time, 0); + timeval_adjust_to_msec (¤t_time); + + /* + * timer at head of list is expired, zero msecs required + */ + if ((timer_from_list->tv.tv_sec < current_time.tv_sec) || + ((timer_from_list->tv.tv_sec == current_time.tv_sec) && + (timer_from_list->tv.tv_usec <= current_time.tv_usec))) { + return (0); + } + time_in_msec = ((timer_from_list->tv.tv_sec - current_time.tv_sec) * 1000) + ((timer_from_list->tv.tv_usec - current_time.tv_usec) / 1000); + + return time_in_msec; +} + +void timerlist_expire (struct timerlist *timerlist) +{ + struct list_head *timer_list; + struct timer *timer_from_list; + struct timeval current_time; + + gettimeofday (¤t_time, 0); + timeval_adjust_to_msec (¤t_time); + + for (timer_list = timerlist->timer_head.next; + timer_list != &timerlist->timer_head;) { + + timer_from_list = list_entry (timer_list, + struct timer, list); + + if ((timer_from_list->tv.tv_sec < current_time.tv_sec) || + ((timer_from_list->tv.tv_sec == current_time.tv_sec) && + (timer_from_list->tv.tv_usec <= current_time.tv_usec))) { + timer_list = timer_list->next; + list_del (&timer_from_list->list); + /* + * This list_init is here to allow multiple deletes + * of a timer without corrupting memory + */ + list_init (&timer_from_list->list); + +#ifdef DEBUG_MULTIPLE_DELETE +timer_from_list->list.next = (struct list_head *)0xdeadbeef; +timer_from_list->list.prev = (struct list_head *)0xdeadbeef; +#endif + timer_from_list->timer_fn (timer_from_list->data); + } else { + break; /* for timer iteration */ + } + } +} diff --git a/exec/tlist.h b/exec/tlist.h index e69de29b..43156b41 100644 --- a/exec/tlist.h +++ b/exec/tlist.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include "../include/list.h" + +#ifndef TLIST_H_DEFINED +#define TLIST_H_DEFINED + +typedef void * timer_handle; + +struct timerlist { + struct list_head timer_head; +}; + +void timerlist_init (struct timerlist *timerlist); + +void timerlist_free (struct timerlist *timerlist); + +timer_handle timerlist_add_future (struct timerlist *timerlist, + void (*timer_fn) (void *data), + void *data, + int msec_in_future); + +void timerlist_del (struct timerlist *timerlist, timer_handle timer_handle); + +void timerlist_expire (struct timerlist *timerlist); + +int timerlist_timeout_msec (struct timerlist *timerlist); + +#endif /* TLIST_H_DEFINED */ diff --git a/include/ais_amf.h b/include/ais_amf.h index e69de29b..196bf2a2 100644 --- a/include/ais_amf.h +++ b/include/ais_amf.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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_AMF_H_DEFINED +#define AIS_AMF_H_DEFINED + +#include "ais_types.h" + +typedef void (*SaAmfHealthcheckCallbackT) ( + SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType); + +typedef void (*SaAmfReadinessStateSetCallbackT) ( + SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState); + +typedef void (*SaAmfComponentTerminateCallbackT) ( + SaInvocationT invocation, + const SaNameT *compName); + +typedef void (*SaAmfCSISetCallbackT) ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor); + +typedef void (*SaAmfCSIRemoveCallbackT) ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags); + +typedef void (*SaAmfProtectionGroupTrackCallbackT) ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error); + +typedef void (*SaAmfExternalComponentRestartCallbackT) ( + SaInvocationT invocation, + const SaNameT *externalCompName); + +typedef void (*SaAmfExternalComponentControlCallbackT) ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction); + +typedef void (*SaAmfPendingOperationConfirmCallbackT) ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags); + +typedef void (*SaAmfPendingOperationExpiredCallbackT) ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags); + +typedef struct { + SaAmfHealthcheckCallbackT + saAmfHealthcheckCallback; + SaAmfReadinessStateSetCallbackT + saAmfReadinessStateSetCallback; + SaAmfComponentTerminateCallbackT + saAmfComponentTerminateCallback; + SaAmfCSISetCallbackT + saAmfCSISetCallback; + SaAmfCSIRemoveCallbackT + saAmfCSIRemoveCallback; + SaAmfProtectionGroupTrackCallbackT + saAmfProtectionGroupTrackCallback; + SaAmfExternalComponentRestartCallbackT + saAmfExternalComponentRestartCallback; + SaAmfExternalComponentControlCallbackT + saAmfExternalComponentControlCallback; + SaAmfPendingOperationConfirmCallbackT + saAmfPendingOperationConfirmCallback; + SaAmfPendingOperationExpiredCallbackT + saAmfPendingOperationExpiredCallback; +} SaAmfCallbacksT; + +/* + * Interfaces + */ +#ifdef __cplusplus +extern "C" { +#endif + +SaErrorT +saAmfInitialize ( + SaAmfHandleT *amfHandle, + const SaAmfCallbacksT *amfCallbacks, + const SaVersionT *version); + +SaErrorT +saAmfSelectionObjectGet ( + const SaAmfHandleT *amfHandle, + SaSelectionObjectT *selectionObject); + +SaErrorT +saAmfDispatch ( + const SaAmfHandleT *amfHandle, + SaDispatchFlagsT dispatchFlags); + +SaErrorT +saAmfFinalize ( + const SaAmfHandleT *amfHandle); + +SaErrorT +saAmfComponentRegister ( + const SaAmfHandleT *amfHandle, + const SaNameT *compName, + const SaNameT *proxyCompName); + +SaErrorT +saAmfComponentUnregister ( + const SaAmfHandleT *amfHandle, + const SaNameT *compName, + const SaNameT *proxyCompName); + +SaErrorT +saAmfCompNameGet ( + const SaAmfHandleT *amfHandle, + SaNameT *compName); + +SaErrorT +saAmfReadinessStateGet ( + const SaNameT *compName, + SaAmfReadinessStateT *readinessState); + +SaErrorT +saAmfStoppingComplete ( + SaInvocationT invocation, + SaErrorT error); + +SaErrorT +saAmfHAStateGet ( + const SaNameT *compName, + const SaNameT *csiName, + SaAmfHAStateT *haState); + +SaErrorT +saAmfProtectionGroupTrackStart ( + const SaAmfHandleT *amfHandle, + const SaNameT *csiName, + SaUint8T trackFlags, + const SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems); + +SaErrorT +saAmfProtectionGroupTrackStop ( + const SaAmfHandleT *amfHandle, + const SaNameT *csiName); + +SaErrorT +saAmfErrorReport ( + const SaNameT *reportingComponent, + const SaNameT *erroneousComponent, + SaTimeT errorDetectionTime, + const SaAmfErrorDescriptorT *errorDescriptor, + const SaAmfAdditionalDataT *additionalData); + +SaErrorT +saAmfErrorCancelAll ( + const SaNameT *compName); + +SaErrorT +saAmfComponentCapabilityModelGet ( + const SaNameT *compName, + SaAmfComponentCapabilityModelT *componentCapabilityModel); + +SaErrorT +saAmfPendingOperationGet ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT *pendingOperationFlags); + +SaErrorT +saAmfResponse ( + SaInvocationT invocation, + SaErrorT error); + +#ifdef __cplusplus +} +#endif + +#endif /* AIS_AMF_H_DEFINED */ diff --git a/include/ais_ckpt.h b/include/ais_ckpt.h index e69de29b..1a3c7c7b 100644 --- a/include/ais_ckpt.h +++ b/include/ais_ckpt.h @@ -0,0 +1,174 @@ + +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 "ais_types.h" + +#ifndef AIS_CKPT_H_DEFINED +#define AIS_CKPT_H_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + +SaErrorT +saCkptInitialize ( + SaCkptHandleT *ckptHandle, + const SaCkptCallbacksT *callbacks, + const SaVersionT *version); + +SaErrorT +saCkptSelectionObjectGet ( + const SaCkptHandleT *ckptHandle, + SaSelectionObjectT *selectionObject); + +SaErrorT +saCkptDispatch ( + const SaCkptHandleT *ckptHandle, + SaDispatchFlagsT dispatchFlags); + +SaErrorT +saCkptFinalize ( + const SaCkptHandleT *ckptHandle); + +SaErrorT +saCkptCheckpointOpen ( + const SaNameT *checkpointName, + const SaCkptCheckpointCreationAttributesT *checkpointCreationAttributes, + SaCkptCheckpointOpenFlagsT checkpointOpenFlags, + SaTimeT timeout, + SaCkptCheckpointHandleT *checkpointHandle); + +SaErrorT +saCkptCheckpointOpenAsync ( + const SaCkptHandleT *ckptHandle, + SaInvocationT invocation, + const SaNameT *checkpointName, + const SaCkptCheckpointCreationAttributesT *checkpointCreationAttributes, + SaCkptCheckpointOpenFlagsT checkpointOpenFlags); + +SaErrorT +saCkptCheckpointClose ( + const SaCkptCheckpointHandleT *checkpointHandle); + +SaErrorT +saCkptCheckpointUnlink ( + const SaNameT *checkpointName); + +SaErrorT +saCkptCheckpointRetentionDurationSet ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaTimeT retentionDuration); + +SaErrorT +saCkptActiveCheckpointSet ( + const SaCkptCheckpointHandleT *checkpointHandle); + +SaErrorT +saCkptCheckpointStatusGet ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptCheckpointStatusT *checkpointStatus); + +SaErrorT +saCkptSectionCreate ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptSectionCreationAttributesT *sectionCreationAttributes, + const void *initialData, + SaUint32T initialDataSize); + + +SaErrorT +saCkptSectionDelete ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptSectionIdT *sectionId); + +SaErrorT +saCkptSectionExpirationTimeSet ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptSectionIdT *sectionId, + SaTimeT expirationTime); + +SaErrorT +saCkptSectionIteratorInitialize ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptSectionsChosenT sectionsChosen, + SaTimeT expirationTime, + SaCkptSectionIteratorT *sectionIterator); + +SaErrorT +saCkptSectionIteratorNext ( + SaCkptSectionIteratorT *sectionIterator, + SaCkptSectionDescriptorT *sectionDescriptor); + +SaErrorT +saCkptSectionIteratorFinalize ( + SaCkptSectionIteratorT *sectionIterator); + +SaErrorT +saCkptCheckpointWrite ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptIOVectorElementT *ioVector, + SaUint32T numberOfElements, + SaUint32T *erroneousVectorIndex); + +SaErrorT +saCkptSectionOverwrite ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptSectionIdT *secitonId, + SaUint8T *dataBuffer, + SaSizeT dataSize); + +SaErrorT +saCkptCheckpointRead ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptIOVectorElementT *ioVector, + SaUint32T numberOfElements, + SaUint32T *erroneousVectorIndex); + +SaErrorT +saCkptCheckpointSynchronize ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaTimeT timeout); + +SaErrorT +saCkptCheckpointSynchronizeAsync ( + const SaCkptHandleT *ckptHandle, + SaInvocationT invocation, + const SaCkptCheckpointHandleT *checkpointHandle); + +#ifdef __cplusplus +} +#endif + +#endif /* AIS_CKPT_H_DEFINED */ diff --git a/include/ais_clm.h b/include/ais_clm.h index e69de29b..ced0bfa9 100644 --- a/include/ais_clm.h +++ b/include/ais_clm.h @@ -0,0 +1,100 @@ + +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 "ais_types.h" + +typedef void (*SaClmClusterNodeGetCallbackT)( + SaInvocationT invocation, + SaClmClusterNodeT *clusterNode, + SaErrorT error); + +typedef void (*SaClmClusterTrackCallbackT) ( + SaClmClusterNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaUint64T viewNumber, + SaErrorT error); + +typedef struct { + SaClmClusterNodeGetCallbackT saClmClusterNodeGetCallback; + SaClmClusterTrackCallbackT saClmClusterTrackCallback; +} SaClmCallbacksT; + +SaErrorT +saClmInitialize ( + SaClmHandleT *clmHandle, + const SaClmCallbacksT *clmCallbacks, + const SaVersionT *version); + + +SaErrorT +saClmSelectionObjectGet ( + const SaClmHandleT *clmHandle, + SaSelectionObjectT *selectionObject); + +SaErrorT +saClmDispatch ( + const SaClmHandleT *clmHandle, + SaDispatchFlagsT dispatchFlags); + +SaErrorT +saClmFinalize ( + SaClmHandleT *clmHandle); + +SaErrorT +saClmClusterTrackStart ( + const SaClmHandleT *clmHandle, + SaUint8T trackFlags, + SaClmClusterNotificationT *notificationBuffer, + SaUint32T numberOfItems); + +SaErrorT +saClmClusterTrackStop ( + const SaClmHandleT *clmHandle); + +SaErrorT +saClmClusterNodeGet ( + SaClmNodeIdT nodeId, + SaTimeT timeout, + SaClmClusterNodeT *clusterNode); + +SaErrorT +saClmClusterNodeGetAsync ( + const SaClmHandleT *clmHandle, + SaInvocationT invocation, + SaClmNodeIdT nodeId, + SaClmClusterNodeT *clusterNode); + + diff --git a/include/ais_msg.h b/include/ais_msg.h index e69de29b..22a836eb 100644 --- a/include/ais_msg.h +++ b/include/ais_msg.h @@ -0,0 +1,728 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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_MSG_H_DEFINED +#define AIS_MSG_H_DEFINED + +#include +#include "ais_types.h" + +enum req_amf_response_interfaces { + MESSAGE_REQ_AMF_RESPONSE_SAAMFHEALTHCHECKCALLBACK = 0x10000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFREADINESSSTATESETCALLBACK = 0x20000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFCOMPONENTTERMINATECALLBACK = 0x30000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFCSISETCALLBACK = 0x40000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFCSIREMOVECALLBACK = 0x50000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFEXTERNALCOMPONENTRESTARTCALLBACK = 0x60000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFEXTERNALCOMPONENTCONTROLCALLBACK = 0x70000000, + MESSAGE_REQ_AMF_RESPONSE_SAAMFPENDINGOPERATIONCONFIRMCALLBACK = 0x80000000 +}; +#define req_amf_response_get_interface(a) (a & 0xf0000000) +#define req_amf_response_get_connection(a) (a & 0x0fffffff) +#define req_amf_response_set(interface,connection) (interface | connection) + +enum req_init_types { + MESSAGE_REQ_CLM_INIT, + MESSAGE_REQ_AMF_INIT, + MESSAGE_REQ_CKPT_INIT, + MESSAGE_REQ_CKPT_CHECKPOINT_INIT, + MESSAGE_REQ_CKPT_SECTIONITERATOR_INIT +}; + +enum res_init_types { + MESSAGE_RES_INIT +}; + +enum req_clm_types { + MESSAGE_REQ_CLM_TRACKSTART, + MESSAGE_REQ_CLM_TRACKSTOP, + MESSAGE_REQ_CLM_NODEGET +}; + +enum res_clm_types { + MESSAGE_RES_CLM_TRACKCALLBACK, + MESSAGE_RES_CLM_NODEGET, + MESSAGE_RES_CLM_NODEGETCALLBACK +}; + +enum req_amf_types { + MESSAGE_REQ_AMF_ACTIVATEPOLL, + MESSAGE_REQ_AMF_COMPONENTREGISTER, + MESSAGE_REQ_AMF_COMPONENTUNREGISTER, + MESSAGE_REQ_AMF_READINESSSTATEGET, + MESSAGE_REQ_AMF_HASTATEGET, + MESSAGE_REQ_AMF_PROTECTIONGROUPTRACKSTART, + MESSAGE_REQ_AMF_PROTECTIONGROUPTRACKSTOP, + MESSAGE_REQ_AMF_ERRORREPORT, + MESSAGE_REQ_AMF_ERRORCANCELALL, + MESSAGE_REQ_AMF_STOPPINGCOMPLETE, + MESSAGE_REQ_AMF_RESPONSE, + MESSAGE_REQ_AMF_COMPONENTCAPABILITYMODELGET +}; + +enum res_amf_types { + MESSAGE_RES_AMF_ACTIVATEPOLL, + MESSAGE_RES_AMF_COMPONENTREGISTER, + MESSAGE_RES_AMF_COMPONENTUNREGISTER, + MESSAGE_RES_AMF_READINESSSTATEGET, + MESSAGE_RES_AMF_HASTATEGET, + MESSAGE_RES_AMF_HEALTHCHECKCALLBACK, + MESSAGE_RES_AMF_READINESSSTATESETCALLBACK, + MESSAGE_RES_AMF_COMPONENTTERMINATECALLBACK, + MESSAGE_RES_AMF_CSISETCALLBACK, + MESSAGE_RES_AMF_CSIREMOVECALLBACK, + MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTART, + MESSAGE_RES_AMF_PROTECTIONGROUPTRACKCALLBACK, + MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTOP, + MESSAGE_RES_AMF_COMPONENTCAPABILITYMODELGET, + MESSAGE_RES_AMF_ERRORREPORT, + MESSAGE_RES_AMF_ERRORCANCELALL +}; + +enum req_lib_ckpt_checkpoint_types { + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTOPEN, + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTOPENASYNC, + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTUNLINK, + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTRETENTIONDURATIONSET, + MESSAGE_REQ_CKPT_CHECKPOINT_ACTIVECHECKPOINTSET, + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTSTATUSGET, + MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONCREATE, + MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONDELETE, + MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONEXPIRATIONTIMESET, + MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONWRITE, + MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONOVERWRITE, + MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONREAD, + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZE, + MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZEASYNC +}; + +enum req_lib_ckpt_sectioniterator_types { + MESSAGE_REQ_CKPT_SECTIONITERATOR_SECTIONITERATORINITIALIZE, + MESSAGE_REQ_CKPT_SECTIONITERATOR_SECTIONITERATORNEXT +}; + +enum res_lib_ckpt_types { + MESSAGE_RES_CKPT_CHECKPOINTOPENASYNC, + MESSAGE_RES_CKPT_CHECKPOINTSYNCHRONIZEASYNC +}; + +enum res_lib_ckpt_checkpoint_types { + MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTOPEN, + MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTUNLINK, + MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTRETENTIONDURATIONSET, + MESSAGE_RES_CKPT_CHECKPOINT_ACTIVECHECKPOINTSET, + MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSTATUSGET, + MESSAGE_RES_CKPT_CHECKPOINT_SECTIONCREATE, + MESSAGE_RES_CKPT_CHECKPOINT_SECTIONDELETE, + MESSAGE_RES_CKPT_CHECKPOINT_SECTIONEXPIRATIONTIMESET, + MESSAGE_RES_CKPT_CHECKPOINT_SECTIONWRITE, + MESSAGE_RES_CKPT_CHECKPOINT_SECTIONOVERWRITE, + MESSAGE_RES_CKPT_CHECKPOINT_SECTIONREAD, + MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZE +}; + +enum res_lib_ckpt_sectioniterator_types { + MESSAGE_RES_CKPT_SECTIONITERATOR_SECTIONITERATORINITIALIZE, + MESSAGE_RES_CKPT_SECTIONITERATOR_SECTIONITERATORNEXT +}; + +enum nodeexec_message_types { + MESSAGE_REQ_EXEC_CLM_NODEJOIN, + MESSAGE_REQ_EXEC_AMF_COMPONENTREGISTER, + MESSAGE_REQ_EXEC_AMF_COMPONENTUNREGISTER, + MESSAGE_REQ_EXEC_AMF_ERRORREPORT, + MESSAGE_REQ_EXEC_AMF_ERRORCANCELALL, + MESSAGE_REQ_EXEC_AMF_READINESSSTATESET, + MESSAGE_REQ_EXEC_AMF_HASTATESET, + MESSAGE_REQ_EXEC_CKPT_CHECKPOINTOPEN, + MESSAGE_REQ_EXEC_CKPT_CHECKPOINTCLOSE, + MESSAGE_REQ_EXEC_CKPT_CHECKPOINTUNLINK, + MESSAGE_REQ_EXEC_CKPT_CHECKPOINTRETENTIONDURATIONSET, + MESSAGE_REQ_EXEC_CKPT_SECTIONCREATE, + MESSAGE_REQ_EXEC_CKPT_SECTIONDELETE, + MESSAGE_REQ_EXEC_CKPT_SECTIONEXPIRATIONTIMESET, + MESSAGE_REQ_EXEC_CKPT_SECTIONWRITE, + MESSAGE_REQ_EXEC_CKPT_SECTIONOVERWRITE, + MESSAGE_REQ_EXEC_CKPT_SECTIONREAD +}; + +#define MESSAGE_MAGIC 0x5a6b7c8d +struct message_header { + int magic; + int size; + int id; +}; + +struct message_source { + int fd; + struct in_addr in_addr; +}; + +struct message_temp { + struct message_header header; + char message_data[0]; +}; + +struct req_execauth_xmit_authkey { + struct message_header header; + int authModule; + unsigned char random[16]; +}; + +struct res_execauth_xmit_signature { + struct message_header header; + unsigned char signature[64]; + unsigned int signature_length; +}; + +struct req_execauth_connection_authorized { + struct message_header header; +}; + +struct req_clm_trackstart { + struct message_header header; + SaUint8T trackFlags; + SaClmClusterNotificationT *notificationBufferAddress; + SaUint32T numberOfItems; +}; + +struct req_lib_init { + struct message_header header; +}; + +struct res_lib_init { + struct message_header header; + SaErrorT error; +}; + +struct req_lib_amf_componentregister { + struct message_header header; + SaNameT compName; + SaNameT proxyCompName; +}; + +struct req_exec_amf_componentregister { + struct message_header header; + struct message_source source; + struct req_lib_amf_componentregister req_lib_amf_componentregister; +}; + +struct res_lib_amf_componentregister { + struct message_header header; + SaErrorT error; +}; + +struct req_lib_amf_componentunregister { + struct message_header header; + SaNameT compName; + SaNameT proxyCompName; +}; + +struct req_exec_amf_componentunregister { + struct message_header header; + struct message_source source; + struct req_lib_amf_componentunregister req_lib_amf_componentunregister; +}; + +struct res_lib_amf_componentunregister { + struct message_header header; + SaErrorT error; +}; + +struct req_amf_readinessstateget { + struct message_header header; + SaNameT compName; +}; + +struct res_amf_readinessstateget { + struct message_header header; + SaAmfReadinessStateT readinessState; + SaErrorT error; +}; + +struct res_amf_healthcheckcallback { + struct message_header header; + int instance; + SaInvocationT invocation; + SaNameT compName; + SaAmfHealthcheckT checkType; +}; + +struct res_amf_readinessstatesetcallback { + struct message_header header; + SaInvocationT invocation; + SaNameT compName; + SaAmfReadinessStateT readinessState; +}; + +struct req_exec_amf_readinessstateset { + struct message_header header; + SaNameT compName; + SaAmfReadinessStateT readinessState; +}; + +struct req_exec_amf_hastateset { + struct message_header header; + SaNameT compName; + SaAmfHAStateT haState; +}; + +struct req_exec_ckpt_checkpointclose { + struct message_header header; + SaNameT checkpointName; +}; + +struct req_exec_ckpt_checkpointretentiondurationset { + struct message_header header; + SaNameT checkpointName; + SaTimeT retentionDuration; +}; + +struct res_amf_componentterminatecallback { + struct message_header header; + SaInvocationT invocation; + SaNameT compName; +}; + +struct req_amf_hastateget { + struct message_header header; + SaNameT compName; + SaNameT csiName; +}; + +struct res_amf_hastateget { + struct message_header header; + SaAmfHAStateT haState; + SaErrorT error; +}; + +struct res_amf_csisetcallback { + struct message_header header; + SaInvocationT invocation; + SaNameT compName; + SaNameT csiName; + SaAmfCSIFlagsT csiFlags; + SaAmfHAStateT haState; + SaNameT activeCompName; + SaAmfCSITransitionDescriptorT transitionDescriptor; +}; + +struct res_amf_csiremovecallback { + struct message_header header; + SaInvocationT invocation; + SaNameT compName; + SaNameT csiName; + SaAmfCSIFlagsT csiFlags; +}; + +struct req_amf_protectiongrouptrackstart { + struct message_header header; + SaNameT csiName; + SaUint8T trackFlags; + SaAmfProtectionGroupNotificationT *notificationBufferAddress; + SaUint32T numberOfItems; +}; + +struct res_amf_protectiongrouptrackstart { + struct message_header header; + SaErrorT error; +}; + + +struct req_amf_protectiongrouptrackstop { + struct message_header header; + SaNameT csiName; +}; + +struct res_amf_protectiongrouptrackstop { + struct message_header header; + SaErrorT error; +}; + +struct res_amf_protectiongrouptrackcallback { + struct message_header header; + SaNameT csiName; + SaAmfProtectionGroupNotificationT *notificationBufferAddress; + SaUint32T numberOfItems; + SaUint32T numberOfMembers; + SaUint32T error; + SaAmfProtectionGroupNotificationT notificationBuffer[0]; +}; + +struct req_lib_amf_errorreport { + struct message_header header; + SaNameT reportingComponent; + SaNameT erroneousComponent; + SaTimeT errorDetectionTime; + SaAmfErrorDescriptorT errorDescriptor; + SaAmfAdditionalDataT additionalData; +}; + +struct req_exec_amf_errorreport { + struct message_header header; + struct message_source source; + struct req_lib_amf_errorreport req_lib_amf_errorreport; +}; + +struct res_lib_amf_errorreport { + struct message_header header; + SaErrorT error; +}; + +struct req_lib_amf_errorcancelall { + struct message_header header; + SaNameT compName; +}; + +struct req_exec_amf_errorcancelall { + struct message_header header; + struct message_source source; + struct req_lib_amf_errorcancelall req_lib_amf_errorcancelall; +}; + +struct res_lib_amf_errorcancelall { + struct message_header header; + SaErrorT error; +}; + +struct req_amf_response { + struct message_header header; + SaInvocationT invocation; + SaErrorT error; +}; + +struct req_amf_stoppingcomplete { + struct message_header header; + SaInvocationT invocation; + SaErrorT error; +}; + +struct req_amf_componentcapabilitymodelget { + struct message_header header; + SaNameT compName; +}; + +struct res_amf_componentcapabilitymodelget { + struct message_header header; + SaAmfComponentCapabilityModelT componentCapabilityModel; + SaErrorT error; +}; + +struct req_amf_activatepoll { + struct message_header header; +}; + +struct res_amf_activatepoll { + struct message_header header; +}; + +struct req_lib_ckpt_checkpointopen { + struct message_header header; + SaNameT checkpointName; + SaCkptCheckpointCreationAttributesT checkpointCreationAttributes; + SaCkptCheckpointOpenFlagsT checkpointOpenFlags; +}; + +struct res_lib_ckpt_checkpointopen { + struct message_header header; + SaErrorT error; +}; + +struct req_exec_ckpt_checkpointopen { + struct message_header header; + struct message_source source; + struct req_lib_ckpt_checkpointopen req_lib_ckpt_checkpointopen; +}; + + +struct req_lib_ckpt_checkpointopenasync { + struct message_header header; + SaNameT checkpointName; + SaCkptCheckpointCreationAttributesT checkpointCreationAttributes; + SaCkptCheckpointOpenFlagsT checkpointOpenFlags; + SaInvocationT invocation; +}; + +struct res_lib_ckpt_checkpointopenasync { + struct message_header header; + SaCkptCheckpointHandleT checkpointHandle; + SaInvocationT invocation; + SaErrorT error; +}; + +struct req_lib_ckpt_checkpointclose { + struct message_header header; +}; + +struct res_lib_ckpt_checkpointclose { + struct message_header header; + SaNameT checkpointName; +}; + +struct req_lib_ckpt_checkpointunlink { + struct message_header header; + SaNameT checkpointName; +}; + +struct res_lib_ckpt_checkpointunlink { + struct message_header header; + SaErrorT error; +}; + +struct req_exec_ckpt_checkpointunlink { + struct message_header header; + struct message_source source; + struct req_lib_ckpt_checkpointunlink req_lib_ckpt_checkpointunlink; +}; + +struct req_lib_ckpt_checkpointretentiondurationset { + struct message_header header; + SaTimeT retentionDuration; +}; + +struct req_lib_ckpt_activecheckpointset { + struct message_header header; +}; + +struct res_lib_ckpt_activecheckpointset { + struct message_header header; + SaErrorT error; +}; + +struct req_lib_ckpt_checkpointstatusget { + struct message_header header; +}; + +struct res_lib_ckpt_checkpointstatusget { + struct message_header header; + SaCkptCheckpointStatusT checkpointStatus; +}; + +struct req_lib_ckpt_sectioncreate { + struct message_header header; + SaUint32T idLen; + SaTimeT expirationTime; + SaUint32T initialDataSize; +}; + +struct res_lib_ckpt_sectioncreate { + struct message_header header; + SaErrorT error; +}; + +struct req_exec_ckpt_sectioncreate { + struct message_header header; + struct message_source source; + SaNameT checkpointName; + struct req_lib_ckpt_sectioncreate req_lib_ckpt_sectioncreate; /* this must be last */ +}; + +struct req_lib_ckpt_sectiondelete { + struct message_header header; + SaUint32T idLen; +}; + +struct res_lib_ckpt_sectiondelete { + struct message_header header; + SaErrorT error; +}; +struct req_exec_ckpt_sectiondelete { + struct message_header header; + struct message_source source; + SaNameT checkpointName; + struct req_lib_ckpt_sectiondelete req_lib_ckpt_sectiondelete; /* this must be last */ +}; + +struct req_lib_ckpt_sectionexpirationtimeset { + struct message_header header; + SaUint32T idLen; + SaTimeT expirationTime; +}; + +struct res_lib_ckpt_sectionexpirationtimeset { + struct message_header header; + SaErrorT error; +}; + +struct req_exec_ckpt_sectionexpirationtimeset { + struct message_header header; + struct message_source source; + SaNameT checkpointName; + struct req_lib_ckpt_sectionexpirationtimeset req_lib_ckpt_sectionexpirationtimeset; +}; + +struct req_lib_ckpt_sectioniteratorinitialize { + struct message_header header; + SaNameT checkpointName; + SaCkptSectionsChosenT sectionsChosen; + SaTimeT expirationTime; +}; + +struct res_lib_ckpt_sectioniteratorinitialize { + struct message_header header; + SaErrorT error; +}; + +struct req_lib_ckpt_sectioniteratornext { + struct message_header header; +}; + +struct res_lib_ckpt_sectioniteratornext { + struct message_header header; + SaCkptSectionDescriptorT sectionDescriptor; + SaErrorT error; +}; + +struct req_lib_ckpt_sectionwrite { + struct message_header header; + SaUint32T idLen; + SaOffsetT dataOffset; + SaOffsetT dataSize; +}; + +struct res_lib_ckpt_sectionwrite { + struct message_header header; + SaErrorT error; +}; + +struct req_exec_ckpt_sectionwrite { + struct message_header header; + struct message_source source; + SaNameT checkpointName; + struct req_lib_ckpt_sectionwrite req_lib_ckpt_sectionwrite; +}; + +struct req_lib_ckpt_sectionoverwrite { + struct message_header header; + SaUint32T idLen; + SaUint32T dataSize; +}; + +struct res_lib_ckpt_sectionoverwrite { + struct message_header header; + SaErrorT error; +}; + +struct req_exec_ckpt_sectionoverwrite { + struct message_header header; + struct message_source source; + SaNameT checkpointName; + struct req_lib_ckpt_sectionoverwrite req_lib_ckpt_sectionoverwrite; +}; + +struct req_lib_ckpt_sectionread { + struct message_header header; + SaUint32T idLen; + SaOffsetT dataOffset; + SaOffsetT dataSize; +}; + +struct res_lib_ckpt_sectionread { + struct message_header header; + SaErrorT error; + SaSizeT dataRead; +}; + +struct req_exec_ckpt_sectionread { + struct message_header header; + struct message_source source; + SaNameT checkpointName; + struct req_lib_ckpt_sectionread req_lib_ckpt_sectionread; +}; + +struct req_lib_ckpt_checkpointsynchronize { + struct message_header header; +}; + +struct res_lib_ckpt_checkpointsynchronize { + struct message_header header; + SaErrorT error; +}; + +struct req_lib_ckpt_checkpointsynchronizeasync { + struct message_header header; + SaInvocationT invocation; +}; + +struct req_clm_trackstop { + struct message_header header; + SaSizeT dataRead; + SaErrorT error; +}; + +struct res_clm_trackcallback { + struct message_header header; + SaUint64T viewNumber; + SaUint32T numberOfItems; + SaUint32T numberOfMembers; + SaClmClusterNotificationT *notificationBufferAddress; + SaClmClusterNotificationT notificationBuffer[0]; +}; + +struct req_clm_nodeget { + struct message_header header; + SaClmClusterNodeT *clusterNodeAddress; + SaInvocationT invocation; + SaClmNodeIdT nodeId; +}; + +struct res_clm_nodeget { + struct message_header header; + SaInvocationT invocation; + SaClmClusterNodeT *clusterNodeAddress; + SaClmClusterNodeT clusterNode; + int valid; +}; + +struct res_clm_nodegetcallback { + struct message_header header; + SaInvocationT invocation; + SaClmClusterNodeT *clusterNodeAddress; + SaClmClusterNodeT clusterNode; + int valid; +}; + +struct req_exec_clm_heartbeat { + struct message_header header; +}; + +struct res_exec_clm_heartbeat { + struct message_header header; +}; + +struct req_exec_clm_nodejoin { + struct message_header header; + SaClmClusterNodeT clusterNode; +}; + +#endif /* AIS_MSG_H_DEFINED */ diff --git a/include/ais_types.h b/include/ais_types.h index e69de29b..a3fbbe4c 100644 --- a/include/ais_types.h +++ b/include/ais_types.h @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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_TYPES_H_DEFINED +#define AIS_TYPES_H_DEFINED + +typedef enum { + SA_FALSE = 0, + SA_TRUE = 1 +} SaBoolT; + +typedef char SaInt8T; +typedef short SaInt16T; +typedef long SaInt32T; +typedef long long SaInt64T; + +typedef unsigned char SaUint8T; +typedef unsigned short SaUint16T; +typedef unsigned long SaUint32T; +typedef unsigned long long SaUint64T; + +typedef SaInt64T SaTimeT; + +#define SA_MAX_NAME_LENGTH 256 +typedef struct { + SaUint16T length; + unsigned char value[SA_MAX_NAME_LENGTH]; +} SaNameT; + +typedef struct { + char releaseCode; + unsigned char major; + unsigned char minor; +} SaVersionT; + +#define SA_TRACK_CURRENT 0x01 +#define SA_TRACK_CHANGES 0x02 +#define SA_TRACK_CHANGES_ONLY 0x04 + +#define SA_CLM_LOCAL_NODE_ID 0x00 + +typedef enum { + SA_DISPATCH_ONE = 1, + SA_DISPATCH_ALL = 2, + SA_DISPATCH_BLOCKING = 3 +} SaDispatchFlagsT; + +typedef enum { + SA_OK = 1, + SA_ERR_LIBRARY = 2, + SA_ERR_VERSION = 3, + SA_ERR_INIT = 4, + SA_ERR_TIMEOUT = 5, + SA_ERR_TRY_AGAIN = 6, + SA_ERR_INVALID_PARAM = 7, + SA_ERR_NO_MEMORY = 8, + SA_ERR_BAD_HANDLE = 9, + SA_ERR_BUSY = 10, + SA_ERR_ACCESS = 11, + SA_ERR_NOT_EXIST = 12, + SA_ERR_NAME_TOO_LONG = 13, + SA_ERR_EXIST = 14, + SA_ERR_NO_SPACE = 15, + SA_ERR_INTERRUPT = 16, + SA_ERR_SYSTEM = 17, + SA_ERR_NAME_NOT_FOUND = 18, + SA_ERR_NO_RESOURCES = 19, + SA_ERR_NOT_SUPPORTED = 20, + SA_ERR_BAD_OPERATION = 21, + SA_ERR_FAILED_OPERATION = 22, + SA_ERR_MESSAGE_ERROR = 23, + SA_ERR_NO_MESSAGE = 24, + SA_ERR_QUEUE_FULL = 25, + SA_ERR_QUEUE_NOT_AVAILABLE = 26, + SA_ERR_BAD_CHECKPOINT = 27, + SA_ERR_BAD_FLAGS = 28, + SA_ERR_SECURITY = 29 +} SaErrorT; + +typedef SaUint32T SaClmNodeIdT; + +typedef int SaClmHandleT; +typedef int SaSelectionObjectT; +typedef int SaInvocationT; + +#define SA_CLM_MAX_ADDRESS_LENGTH 64 +typedef struct { + SaUint8T length; + unsigned char value[SA_CLM_MAX_ADDRESS_LENGTH]; +} SaClmNodeAddressT; + +typedef struct { + SaClmNodeIdT nodeId; + SaClmNodeAddressT nodeAddress; + SaNameT nodeName; + SaNameT clusterName; + SaBoolT member; + SaTimeT bootTimestamp; +} SaClmClusterNodeT; + +typedef enum { + SA_CLM_NODE_NO_CHANGE = 1, + SA_CLM_NODE_JOINED = 2, + SA_CLM_NODE_LEFT = 3 +} SaClmClusterChangesT; + +typedef struct { + SaClmClusterNodeT clusterNode; + SaClmClusterChangesT clusterChanges; +} SaClmClusterNotificationT; + +/* + * AMF Definitions + */ +typedef int SaAmfHandleT; + +typedef enum { + SA_AMF_HEARTBEAT = 1, + SA_AMF_HEALTHCHECK_LEVEL1 = 2, + SA_AMF_HEALTHCHECK_LEVEL2 = 3, + SA_AMF_HEALTHCHECK_LEVEL3 = 4, +} SaAmfHealthcheckT; + +typedef enum { + SA_AMF_OUT_OF_SERVICE = 1, + SA_AMF_IN_SERVICE = 2, + SA_AMF_STOPPING = 3 +} SaAmfReadinessStateT; + +typedef enum { + SA_AMF_ACTIVE = 1, + SA_AMF_STANDBY = 2, + SA_AMF_QUIESCED = 3 +} SaAmfHAStateT; + +typedef enum { + SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE_AND_Y_STANDBY = 1, + SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE_OR_Y_STANDBY = 2, + SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE_OR_Y_STANDBY = 3, + SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE_OR_1_STANDBY = 4, + SA_AMF_COMPONENT_CAPABILITY_X_ACTIVE = 5, + SA_AMF_COMPONENT_CAPABILITY_1_ACTIVE = 6, + SA_AMF_COMPONENT_CAPABILITY_NO_ACTIVE = 7, +} SaAmfComponentCapabilityModelT; + +#define SA_AMF_CSI_ADD_NEW_ISTANCE 0x01 +#define SA_AMF_CSI_ALL_INSTANCES 0x02 + +typedef SaUint32T SaAmfCSIFlagsT; + +typedef enum { + SA_AMF_CSI_NEW_ASSIGN = 1, + SA_AMF_CSI_QUIESCED = 2, + SA_AMF_CSI_NOT_QUIESCED = 3, + SA_AMF_CSI_STILL_ACTIVE = 4 +} SaAmfCSITransitionDescriptorT; + +typedef enum { + SA_AMF_RESET = 1, + SA_AMF_REBOOT = 2, + SA_AMF_POWER_ON = 3, + SA_AMF_POWER_OFF = 4 +} SaAmfExternalComponentActionT; + +#define SA_AMF_SWITCHOVER_OPERATION 0x01 +#define SA_AMF_SHUTDOWN_OPERATION 0x02 +typedef SaUint32T SaAmfPendingOperationFlagsT; + +typedef struct { + SaNameT compName; + SaAmfReadinessStateT readinessState; + SaAmfHAStateT haState; +} SaAmfProtectionGroupMemberT; + +typedef enum { + SA_AMF_PROTECTION_GROUP_NO_CHANGE = 1, + SA_AMF_PROTECTION_GROUP_ADDED = 2, + SA_AMF_PROTECTION_GROUP_REMOVED = 3, + SA_AMF_PROTECTION_GROUP_STATE_CHANGE = 4 +} SaAmfProtectionGroupChangesT; + +typedef struct { + SaAmfProtectionGroupMemberT member; + SaAmfProtectionGroupChangesT change; +} SaAmfProtectionGroupNotificationT; + +typedef enum { + SA_AMF_COMMUNICATION_ALARM_TYPE = 1, + SA_AMF_QUALITY_OF_SERVICE_ALARM_TYPE = 2, + SA_AMF_PROCESSING_ERROR_ALARM_TYPE = 3, + SA_AMF_EQUIPMENT_ALARM_TYPE = 4, + SA_AMF_ENVIRONMENTAL_ALARM_TYPE = 5 +} SaAmfErrorReportTypeT; + +typedef enum { + SA_AMF_APPLICATION_SUBSYSTEM_FAILURE = 1, + SA_AMF_BANDWIDTH_REDUCED = 2, + SA_AMF_CALL_ESTABLISHMENT_ERROR = 3, + SA_AMF_COMMUNICATION_PROTOCOL_ERROR = 4, + SA_AMF_COMMUNICATION_SUBSYSTEM_FAILURE = 5, + SA_AMF_CONFIGURATION_ERROR = 6, + SA_AMF_CONGESTION = 7, + SA_AMF_CORRUPT_DATA = 8, + SA_AMF_CPU_CYCLES_LIMIT_EXCEEDED = 9, + SA_AMF_EQUIPMENT_MALFUNCTION = 10, + SA_AMF_FILE_ERROR = 11, + SA_AMF_IO_DEVICE_ERROR = 12, + SA_AMF_LAN_ERROR, SA_AMF_OUT_OF_MEMORY = 13, + SA_AMF_PERFORMANCE_DEGRADED = 14, + SA_AMF_PROCESSOR_PROBLEM = 15, + SA_AMF_RECEIVE_FAILURE = 16, + SA_AMF_REMOTE_NODE_TRNASMISSION_ERROR = 17, + SA_AMF_RESOURCE_AT_OR_NEARING_CAPACITY = 18, + SA_AMF_RESPONSE_TIME_EXCESSIVE = 19, + SA_AMF_RETRANSMISSION_RATE_EXCESSIVE = 20, + SA_AMF_SOFTWARE_ERROR = 21, + SA_AMF_SOFTWARE_PROGRAM_ABNORMALLY_TERMINATED = 22, + SA_AMF_SOFTWARE_PROGRAM_ERROR = 23, + SA_AMF_STORAGE_CAPACITY_PROBLEM = 24, + SA_AMF_TIMING_PROBLEM = 25, + SA_AMF_UNDERLYING_REOUSRCE_UNAVAILABLE = 26, + SA_AMF_INTERNAL_ERROR = 27, + SA_AMF_NO_SERVICE_ERROR = 28, + SA_AMF_SOFTWARE_LIBRARY_ERROR = 29, + SA_AMF_NOT_RESPONDING = 30 +} SaAmfProbableCauseT; + +typedef enum { + SA_AMF_CLEARED = 1, + SA_AMF_NO_IMPACT = 2, + SA_AMF_INDETERMINATE = 3, + SA_AMF_CRITICAL = 4, + SA_AMF_MAJOR = 5, + SA_AMF_WEDGED_COMPONENT_FAILURE = 6, + SA_AMF_COMPONENT_TERMINATED_FAILURE = 7, + SA_AMF_NODE_FAILURE = 8, + SA_AMF_MINOR = 9, + SA_AMF_WARNING = 10 +} SaAmfErrorImpactAndSeverityT; + +typedef enum { + SA_AMF_NO_RECOMMENDATION = 1, + SA_AMF_INTERNALLY_RECOVERED = 2, + SA_AMF_COMPONENT_RESTART = 3, + SA_AMF_COMPONENT_FAILOVER = 4, + SA_AMF_NODE_SWITCHOVER = 5, + SA_AMF_NODE_FAILOVER = 6, + SA_AMF_NODE_FAILFAST = 7, + SA_AMF_CLUSTER_RESET = 8 +} SaAmfRecommendedRecoveryT; + +typedef struct { + SaAmfErrorReportTypeT errorReportType; + SaAmfProbableCauseT probableCause; + SaAmfErrorImpactAndSeverityT errorImpactAndSeverity; + SaAmfRecommendedRecoveryT recommendedRecovery; +} SaAmfErrorDescriptorT; + +typedef int SaSizeT; +#define SA_AMF_OPAQUE_BUFFER_SIZE_MAX 512 +typedef struct { + char *buffer; + SaSizeT size; +} SaAmfErrorBufferT; + +typedef struct { + SaAmfErrorBufferT *specificProblem; + SaAmfErrorBufferT *additionalText; + SaAmfErrorBufferT *additionalInformation; +} SaAmfAdditionalDataT; + +typedef int SaCkptHandleT; + +typedef int SaCkptCheckpointHandleT; + +typedef int SaCkptSectionIteratorT; + +#define SA_CKPT_WR_ALL_REPLICAS 0x1 +#define SA_CKPT_WR_ACTIVE_REPLICA 0x2 +#define SA_CKPT_WR_ACTIVE_REPLICA_WEAK 0x4 + +typedef SaUint32T SaCkptCheckpointCreationFlagsT; + +typedef struct { + SaCkptCheckpointCreationFlagsT creationFlags; + SaSizeT checkpointSize; + SaTimeT retentionDuration; + SaUint32T maxSections; + SaSizeT maxSectionSize; + SaUint32T maxSectionIdSize; +} SaCkptCheckpointCreationAttributesT; + +#define SA_CKPT_CHECKPOINT_READ 0x1 +#define SA_CKPT_CHECKPOINT_WRITE 0x2 +#define SA_CKPT_CHECKPOINT_COLOCATED 0x4 +typedef SaUint32T SaCkptCheckpointOpenFlagsT; + +#define SA_CKPT_DEFAULT_SECTION_ID { 0, 0 } +#define SA_CKPT_GENERATED_SECTION_ID { 0, 0 } + +typedef struct { + SaUint8T *id; + SaUint32T idLen; +} SaCkptSectionIdT; + +typedef struct { + SaCkptSectionIdT *sectionId; + SaTimeT expirationTime; +} SaCkptSectionCreationAttributesT; + +typedef enum { + SA_CKPT_SECTION_VALID = 1, + SA_CKPT_SECTION_CORRUPTED = 2 +} SaCkptSectionStateT; + +typedef struct { + SaCkptSectionIdT sectionId; + SaTimeT expirationTime; + SaSizeT sectionSize; + SaCkptSectionStateT sectionState; + SaTimeT lastUpdate; +} SaCkptSectionDescriptorT; + +typedef enum { + SA_CKPT_SECTIONS_FOREVER = 1, + SA_CKPT_SECTIONS_LEQ_EXPIRATION_TIME = 2, + SA_CKPT_SECTIONS_GEQ_EXPIRATION_TIME = 3, + SA_CKPT_SECTIONS_CORRUPTED = 4, + SA_CKPT_SECTIONS_ANY = 5, +} SaCkptSectionsChosenT; + +// SaOffsetT is not defined in the specification ERRATA +typedef SaUint32T SaOffsetT; + +typedef struct { + SaCkptSectionIdT sectionId; + void *dataBuffer; + SaSizeT dataSize; + SaOffsetT dataOffset; + SaSizeT readSize; +} SaCkptIOVectorElementT; + +typedef struct { + SaCkptCheckpointCreationAttributesT checkpointCreationAttributes; + SaUint32T numberOfSections; + SaUint32T memoryUsed; +} SaCkptCheckpointStatusT; + +typedef void (*SaCkptCheckpointOpenCallbackT) ( + SaInvocationT invocation, + const SaCkptCheckpointHandleT *checkpointHandle, + SaErrorT error); + +typedef void (*SaCkptCheckpointSynchronizeCallbackT) ( + SaInvocationT invocation, + SaErrorT error); + +typedef struct { + SaCkptCheckpointOpenCallbackT saCkptCheckpointOpenCallback; + SaCkptCheckpointSynchronizeCallbackT saCkptCheckpointSynchronizeCallback; +} SaCkptCallbacksT; + +#endif /* AIS_TYPES_H_DEFINED */ diff --git a/include/list.h b/include/list.h index e69de29b..b37e742a 100644 --- a/include/list.h +++ b/include/list.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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. + */ +/* + * This implementation uses the same API as the linux kernel to + * help us kernel developers easily use the list primatives + */ +#ifndef LIST_H_DEFINED +#define LIST_H_DEFINED + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +#define DECLARE_LIST_INIT(name) \ + struct list_head name = { &(name), &(name) } + +static void inline list_init (struct list_head *head) +{ + head->next = head; + head->prev = head; +}; + +static void inline list_add (struct list_head *new, struct list_head *head) +{ + head->next->prev = new; + new->next = head->next; + new->prev = head; + head->next = new; +} +static void inline list_del (struct list_head *remove) +{ + remove->next->prev = remove->prev; + remove->prev->next = remove->next; +#ifdef DEBUG + remove->next = (struct list_head *)0xdeadb33f; + remove->prev = (struct list_head *)0xdeadb33f; +#endif +} + +#define list_entry(ptr,type,member)\ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +#endif /* LIST_H_DEFINED */ diff --git a/include/queue.h b/include/queue.h index e69de29b..3d748ee0 100644 --- a/include/queue.h +++ b/include/queue.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 QUEUE_H_DEFINED +#define QUEUE_H_DEFINED + +#include "assert.h" + +struct queue { + int head; + int tail; + int used; + int usedhw; + int size; + void *items; + int size_per_item; + int iterator; +}; + +static inline int queue_init (struct queue *queue, int queue_items, int size_per_item) { + queue->head = 0; + queue->tail = queue_items - 1; + queue->used = 0; + queue->usedhw = 0; + queue->size = queue_items; + queue->size_per_item = size_per_item; + + queue->items = malloc (queue_items * size_per_item); + if (queue->items == 0) { + return (-ENOMEM); + } + memset (queue->items, 0, queue_items * size_per_item); + return (0); +} + +static inline int queue_reinit (struct queue *queue) +{ + queue->head = 0; + queue->tail = queue->size - 1; + queue->used = 0; + queue->usedhw = 0; + + memset (queue->items, 0, queue->size * queue->size_per_item); + return (0); +} + +static inline void queue_free (struct queue *queue) { + free (queue->items); +} + +static inline int queue_is_full (struct queue *queue) { + return (queue->size - 1 == queue->used); +} + +static inline int queue_is_empty (struct queue *queue) { + return (queue->used == 0); +} + +static inline void queue_item_add (struct queue *queue, void *item) +{ + char *queue_item; + int queue_position; + + queue_position = queue->head; + queue_item = queue->items; + queue_item += queue_position * queue->size_per_item; + memcpy (queue_item, item, queue->size_per_item); + + assert (queue->tail != queue->head); + + queue->head = (queue->head + 1) % queue->size; + queue->used++; + if (queue->used > queue->usedhw) { + queue->usedhw = queue->used; + } +} + +static inline void *queue_item_get (struct queue *queue) +{ + char *queue_item; + int queue_position; + + queue_position = (queue->tail + 1) % queue->size; + queue_item = queue->items; + queue_item += queue_position * queue->size_per_item; + return ((void *)queue_item); +} + +static inline void queue_item_remove (struct queue *queue) { + queue->tail = (queue->tail + 1) % queue->size; + + assert (queue->tail != queue->head); + + queue->used--; +} + +static inline void queue_items_remove (struct queue *queue, int rel_count) +{ + queue->tail = (queue->tail + rel_count) % queue->size; + + assert (queue->tail != queue->head); + + queue->used -= rel_count; +} + + +static inline void queue_item_iterator_init (struct queue *queue) +{ + queue->iterator = (queue->tail + 1) % queue->size; +} + +static inline void *queue_item_iterator_get (struct queue *queue) +{ + char *queue_item; + int queue_position; + + queue_position = (queue->iterator) % queue->size; + if (queue->iterator == queue->head) { + return (0); + } + queue_item = queue->items; + queue_item += queue_position * queue->size_per_item; + return ((void *)queue_item); +} + +static inline int queue_item_iterator_next (struct queue *queue) +{ + queue->iterator = (queue->iterator + 1) % queue->size; + + return (queue->iterator == queue->head); +} + +#endif /* QUEUE_H_DEFINED */ diff --git a/include/sq.h b/include/sq.h index e69de29b..a322903b 100644 --- a/include/sq.h +++ b/include/sq.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 SORTQUEUE_H_DEFINED +#define SORTQUEUE_H_DEFINED + +#include "errno.h" + +struct sq { + int head; + int size; + void *items; + unsigned char *items_inuse; + int size_per_item; + int head_seqid; + int item_count; +}; + +static inline int sq_init ( + struct sq *sq, + int item_count, + int size_per_item, + int head_seqid) +{ + sq->head = 0; + sq->size = item_count; + sq->size_per_item = size_per_item; + sq->head_seqid = head_seqid; + sq->item_count = item_count; + + sq->items = (void *)malloc (item_count * size_per_item); + if (sq->items == 0) { + return (-ENOMEM); + } + memset (sq->items, 0, item_count * size_per_item); + + sq->items_inuse = (void *)malloc (item_count * sizeof (char)); + memset (sq->items_inuse, 0, item_count * sizeof (char)); + return (0); +} + +static inline void sq_reinit (struct sq *sq, int head_seqid) +{ + sq->head = 0; + sq->head_seqid = head_seqid; + + memset (sq->items, 0, sq->item_count * sq->size_per_item); + memset (sq->items_inuse, 0, sq->item_count * sizeof (char)); +} + +static inline void sq_free (struct sq *sq) { + free (sq->items); + free (sq->items_inuse); +} + +static inline int sq_item_add ( + struct sq *sq, + void *item, + int seqid) +{ + char *sq_item; + int sq_position; + + if (seqid - sq->head_seqid >= sq->size) { + return E2BIG; + } + sq_position = (sq->head + seqid - sq->head_seqid) % sq->size; +//printf ("item add %d %d %d\n", sq_position, seqid, sq->head_seqid); + sq_item = sq->items; + sq_item += sq_position * sq->size_per_item; + memcpy (sq_item, item, sq->size_per_item); + sq->items_inuse[sq_position] = 1; + + return (0); +} + +static inline int sq_item_inuse ( + struct sq *sq, + int seq_id) { + + int sq_position; + + sq_position = (sq->head - sq->head_seqid + seq_id) % sq->size; +//printf ("in use %d\n", sq_position); + return (sq->items_inuse[sq_position]); +} + +static inline int sq_size_get ( + struct sq *sq) +{ + return sq->size; +} + +static inline int sq_item_get ( + struct sq *sq, + int seq_id, + void **sq_item_out) +{ + char *sq_item; + int sq_position; + +if (seq_id == -1) { + return (ENOENT); +} + assert (seq_id < (sq->head_seqid + sq->size)); + sq_position = (sq->head - sq->head_seqid + seq_id) % sq->size; +//printf ("ITEMGET %d %d %d %d\n", sq_position, sq->head, sq->head_seqid, seq_id); +assert (sq_position >= 0); +//printf ("itme get in use %d\n", sq_position); + if (sq->items_inuse[sq_position] == 0) { +//printf ("ENOENT\n"); + return (ENOENT); + } + sq_item = sq->items; + sq_item += sq_position * sq->size_per_item; + *sq_item_out = sq_item; + return (0); +} + +static inline void sq_items_release (struct sq *sq, int seqid) +{ + int oldhead; + char *sq_item; + + if (seqid < sq->head_seqid) { +//printf ("%d %d\n", seqid, sq->head_seqid); + return; + } +//printf ("releasing %d\n", seqid); + + oldhead = sq->head; + +//printf ("before sq->head %d\n", sq->head); + sq->head = (sq->head + seqid - sq->head_seqid + 1) % sq->size; +//printf ("after sq->head %d\n", sq->head); + if ((oldhead + seqid - sq->head_seqid + 1) > sq->size) { +//printf ("memset 1\n"); +//printf ("%d %d %d %d\n", seqid, sq->head_seqid, sq->head, sq->size); + memset (&sq->items_inuse[oldhead], 0, sq->size - oldhead); + memset (sq->items_inuse, 0, sq->head * sizeof (char)); +//printf ("SIZEOF %d %d\n", sq->head, sq->head * sizeof (char)); +// memset (sq->items, 0, (sq->head) * (sq->size_per_item)); + } else { +assert (seqid - sq->head_seqid + 1); +//printf ("memset 2\n"); +//printf ("releasing %d for %d\n", oldhead, seqid - sq->head_seqid + 1); + memset (&sq->items_inuse[oldhead - 1], 0, (seqid - sq->head_seqid + 2) * sizeof (char)); + sq_item = sq->items; + sq_item += oldhead * sq->size_per_item; +// memset (sq_item[oldhead], 0, (seqid - sq->head_seqid + 1) * (sq->size_per_item)); + } + sq->head_seqid = seqid + 1; +} + +#endif /* SORTQUEUE_H_DEFINED */ diff --git a/init/ais b/init/ais index e69de29b..f2d437e3 100644 --- a/init/ais +++ b/init/ais @@ -0,0 +1,28 @@ +#! /bin/sh +# +# Application Interface Specification Startup +# chkconfig: 2345 20 20 + +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +test -f /usr/sbin/aisexec | exit 0 + +case "$1" in + start) + echo -n "Starting Application Interface Specification Executive: " + start-stop-daemon --start --quiet --exec /usr/sbin/aisexec + echo "." + + ;; + stop) + echo -n "Stopping Application Interface Specification Executive: " + start-stop-daemon --stop --quiet --exec /usr/sbin/aisexec + echo "." + ;; + *) + echo "Usage: /etc/init.d/ais {start|stop}" >&2 + exit 1 + ;; +esac + + diff --git a/lib/Makefile b/lib/Makefile index e69de29b..1b2595db 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -0,0 +1,56 @@ +# 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. +# Production mode flags +#CFLAGS = -O3 -Wall +#LDFLAGS = + +# Debug mode flags +CFLAGS = -g -fPIC -DDEBUG -Wall +LDFLAGS = -g + +# Profile mode flags +#CFLAGS = -O3 -pg -fPIC -DDEBUG +#LDFLAGS = -pg + +CFLAGS += -fPIC + +all:libais.a libais.so.1.0 + +libais.a: util.o amf.o clm.o ckpt.o + $(AR) -rc libais.a util.o amf.o clm.o ckpt.o + +libais.so.1.0: util.o amf.o clm.o ckpt.o + $(CC) -shared -Wl,-soname,libais.so.1 util.o amf.o clm.o ckpt.o -o $@ + rm -f libais.so.1 libais.so + ln -s libais.so.1.0 libais.so.1 + ln -s libais.so.1.0 libais.so + +clean: + rm -f *.o libais.so* libais.a diff --git a/lib/amf.c b/lib/amf.c index e69de29b..4aada7f5 100644 --- a/lib/amf.c +++ b/lib/amf.c @@ -0,0 +1,938 @@ + +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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. + */ + +/* + * thread locking model is as follows + * + * APIs that use handles: + * + * Every handle database has a lock. + * Each interface started with SaAmfInitialize has a lock. + * Handle database lock is taken. + * amfInstance lock is taken. + * Handle database lock is released early. + * amfInstance lock is released after amfInstance is out of use. + * + * Finalize API: + * Handle database lock is taken + * amf instance lock is taken + * handle is removed + * amf instance lock is released + * handle database lock is released + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_amf.h" +#include "../include/ais_msg.h" +#include "util.h" + +struct message_overlay { + struct message_header header; + char data[4096]; +}; + +/* + * Data structure for instance data + */ +struct amfInstance { + int fd; + SaAmfCallbacksT callbacks; + struct queue inq; + SaNameT compName; + int compRegistered; + struct message_overlay message; + pthread_mutex_t mutex; +}; +#define AMFINSTANCE_MUTEX_OFFSET offset_of(struct amfInstance, mutex) + +/* + * All instances in one database + */ +static struct saHandleDatabase amfHandleDatabase = { + handleCount: 0, + handles: 0, + generation: 0, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +/* + * Versions supported + */ +static SaVersionT amfVersionsSupported[] = { + { 'A', 1, 1 }, + { 'a', 1, 1 } +}; + +static struct saVersionDatabase amfVersionDatabase = { + sizeof (amfVersionsSupported) / sizeof (SaVersionT), + amfVersionsSupported +}; + +/* + * Implementation + */ +SaErrorT +saAmfInitialize ( + SaAmfHandleT *amfHandle, + const SaAmfCallbacksT *amfCallbacks, + const SaVersionT *version) +{ + struct amfInstance *amfInstance; + SaErrorT error = SA_OK; + + error = saVersionVerify (&amfVersionDatabase, version); + if (error != SA_OK) { + goto error_nofree; + } + + error = saHandleCreate (&amfHandleDatabase, (void *)&amfInstance, + sizeof (struct amfInstance), amfHandle); + if (error != SA_OK) { + goto error_nofree; + } + + /* + * An inq is needed to store async messages while waiting for a + * sync response + */ + error = saQueueInit (&amfInstance->inq, 512, sizeof (void *)); + if (error != SA_OK) { + goto error_free; + } + + error = saServiceConnect (&amfInstance->fd, MESSAGE_REQ_AMF_INIT); + if (error != SA_OK) { + goto error_free2; + } + + memcpy (&amfInstance->callbacks, amfCallbacks, sizeof (SaAmfCallbacksT)); + + pthread_mutex_init (&amfInstance->mutex, NULL); + + return (SA_OK); + +error_free2: + free (amfInstance->inq.items); +error_free: + saHandleRemove (&amfHandleDatabase, *amfHandle); +error_nofree: + return (error); +} + +SaErrorT +saAmfSelectionObjectGet ( + const SaAmfHandleT *amfHandle, + SaSelectionObjectT *selectionObject) +{ + struct amfInstance *amfInstance; + SaErrorT error; + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + *selectionObject = amfInstance->fd; + + pthread_mutex_unlock (&amfInstance->mutex); + return (SA_OK); +} + +SaErrorT +saAmfDispatch ( + const SaAmfHandleT *amfHandle, + SaDispatchFlagsT dispatchFlags) +{ + struct pollfd ufds; + int timeout = -1; + SaErrorT error; + int dispatch_avail; + struct amfInstance *amfInstance; + SaAmfCallbacksT callbacks; + struct res_amf_healthcheckcallback *res_amf_healthcheckcallback; + struct res_amf_readinessstatesetcallback *res_amf_readinessstatesetcallback; + struct res_amf_csisetcallback *res_amf_csisetcallback; + struct res_amf_csiremovecallback *res_amf_csiremovecallback; + struct res_amf_protectiongrouptrackcallback *res_amf_protectiongrouptrackcallback; + struct message_header **queue_msg; + struct message_header *msg; + int empty; + int ignore_dispatch = 0; + int cont = 1; /* always continue do loop except when set to 0 */ + int handle_verified = 0; + int poll_fd; + unsigned int gen_first; + unsigned int gen_second; + + /* + * Timeout instantly for SA_DISPATCH_ALL + */ + if (dispatchFlags == SA_DISPATCH_ALL) { + timeout = 0; + } + + do { + /* + * If flags are SA_DISPATCH_BLOCKING and handle has been + * verified, return SA_OK because a Finalize has been + * called. Else return error from saHandleConvert + */ + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, &gen_first); + if (error != SA_OK) { + return (handle_verified ? SA_OK : error); + } + handle_verified = 1; + + poll_fd = amfInstance->fd; + + /* + * Unlock mutex for potentially long wait in select. If fd + * is closed by amfFinalize in select, select will return + */ + pthread_mutex_unlock (&amfInstance->mutex); + + /* + * Read data directly from socket + */ + ufds.fd = poll_fd; + ufds.events = POLLIN; + ufds.revents = 0; + + error = saPollRetry (&ufds, 1, timeout); + if (error != SA_OK) { + goto error_nounlock; + } + + dispatch_avail = ufds.revents & POLLIN; + if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) { + break; /* exit do while cont is 1 loop */ + } else + if (dispatch_avail == 0) { + continue; /* next select */ + } + + /* + * Re-verify amfHandle + */ + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, &gen_second); + if (error != SA_OK) { + return (handle_verified ? SA_OK : error); + } + + /* + * Handle has been removed and then reallocated + */ + if (gen_first != gen_second) { + return (SA_OK); + } + saQueueIsEmpty(&amfInstance->inq, &empty); + if (empty == 0) { + /* + * Queue is not empty, read data from queue + */ + saQueueItemGet (&amfInstance->inq, (void *)&queue_msg); + msg = *queue_msg; + memcpy (&amfInstance->message, msg, msg->size); + saQueueItemRemove (&amfInstance->inq); + } else { + /* + * Queue empty, read response from socket + */ + error = saRecvRetry (amfInstance->fd, &amfInstance->message.header, sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + if (amfInstance->message.header.size > sizeof (struct message_header)) { + error = saRecvRetry (amfInstance->fd, &amfInstance->message.data, + amfInstance->message.header.size - sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + } + } + /* + * Make copy of callbacks, unlock instance, and call callback + * A risk of this dispatch method is that the callback routines may + * operate at the same time that amfFinalize has been called. + */ + memcpy (&callbacks, &amfInstance->callbacks, sizeof (SaAmfCallbacksT)); + + pthread_mutex_unlock (&amfInstance->mutex); + + /* + * Dispatch incoming response + */ + switch (amfInstance->message.header.id) { + case MESSAGE_RES_AMF_ACTIVATEPOLL: + /* + * This is a do nothing message which the node executive sends + * to activate the file handle in poll when the library has + * queued a message into amfHandle->inq + * The dispatch is ignored for the following two cases: + * 1) setting of timeout to zero for the DISPATCH_ALL case + * 2) expiration of the do loop for the DISPATCH_ONE case + */ + ignore_dispatch = 1; + break; + + case MESSAGE_RES_AMF_HEALTHCHECKCALLBACK: + res_amf_healthcheckcallback = (struct res_amf_healthcheckcallback *)&amfInstance->message; + pthread_mutex_unlock (&amfInstance->mutex); + + callbacks.saAmfHealthcheckCallback ( + res_amf_healthcheckcallback->invocation, + &res_amf_healthcheckcallback->compName, + res_amf_healthcheckcallback->checkType); + break; + + case MESSAGE_RES_AMF_READINESSSTATESETCALLBACK: + res_amf_readinessstatesetcallback = (struct res_amf_readinessstatesetcallback *)&amfInstance->message; + callbacks.saAmfReadinessStateSetCallback ( + res_amf_readinessstatesetcallback->invocation, + &res_amf_readinessstatesetcallback->compName, + res_amf_readinessstatesetcallback->readinessState); + break; + + case MESSAGE_RES_AMF_CSISETCALLBACK: + res_amf_csisetcallback = (struct res_amf_csisetcallback *)&amfInstance->message; + callbacks.saAmfCSISetCallback ( + res_amf_csisetcallback->invocation, + &res_amf_csisetcallback->compName, + &res_amf_csisetcallback->csiName, + res_amf_csisetcallback->csiFlags, + &res_amf_csisetcallback->haState, + &res_amf_csisetcallback->activeCompName, + res_amf_csisetcallback->transitionDescriptor); + break; + + case MESSAGE_RES_AMF_CSIREMOVECALLBACK: + res_amf_csiremovecallback = (struct res_amf_csiremovecallback *)&amfInstance->message; + callbacks.saAmfCSIRemoveCallback ( + res_amf_csiremovecallback->invocation, + &res_amf_csiremovecallback->compName, + &res_amf_csiremovecallback->csiName, + &res_amf_csiremovecallback->csiFlags); + break; + + case MESSAGE_RES_AMF_PROTECTIONGROUPTRACKCALLBACK: + res_amf_protectiongrouptrackcallback = (struct res_amf_protectiongrouptrackcallback *)&amfInstance->message; + memcpy (res_amf_protectiongrouptrackcallback->notificationBufferAddress, + res_amf_protectiongrouptrackcallback->notificationBuffer, + res_amf_protectiongrouptrackcallback->numberOfItems * sizeof (SaAmfProtectionGroupNotificationT)); + callbacks.saAmfProtectionGroupTrackCallback( + &res_amf_protectiongrouptrackcallback->csiName, + res_amf_protectiongrouptrackcallback->notificationBufferAddress, + res_amf_protectiongrouptrackcallback->numberOfItems, + res_amf_protectiongrouptrackcallback->numberOfMembers, + res_amf_protectiongrouptrackcallback->error); + break; + + default: + error = SA_ERR_LIBRARY; + goto error_nounlock; + break; + } + + /* + * Determine if more messages should be processed + */ + switch (dispatchFlags) { + case SA_DISPATCH_ONE: + if (ignore_dispatch) { + ignore_dispatch = 0; + } else { + cont = 0; + } + break; + case SA_DISPATCH_ALL: + if (ignore_dispatch) { + ignore_dispatch = 0; + } + break; + case SA_DISPATCH_BLOCKING: + break; + } + } while (cont); + + return (error); + +error_unlock: + pthread_mutex_unlock (&amfInstance->mutex); +error_nounlock: + return (error); +} + +SaErrorT +saAmfFinalize ( + const SaAmfHandleT *amfHandle) +{ + struct amfInstance *amfInstance; + SaErrorT error; + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET | HANDLECONVERT_DONTUNLOCKDB, 0); + if (error != SA_OK) { + return (error); + } + + shutdown (amfInstance->fd, 0); + close (amfInstance->fd); + free (amfInstance->inq.items); + + error = saHandleRemove (&amfHandleDatabase, *amfHandle); + + pthread_mutex_unlock (&amfInstance->mutex); + + saHandleUnlockDatabase (&amfHandleDatabase); + + return (error); +} + +SaErrorT +saAmfComponentRegister ( + const SaAmfHandleT *amfHandle, + const SaNameT *compName, + const SaNameT *proxyCompName) +{ + struct amfInstance *amfInstance; + SaErrorT error; + struct req_lib_amf_componentregister req_lib_amf_componentregister; + struct res_lib_amf_componentregister *res_lib_amf_componentregister; + + req_lib_amf_componentregister.header.magic = MESSAGE_MAGIC; + req_lib_amf_componentregister.header.size = sizeof (struct req_lib_amf_componentregister); + req_lib_amf_componentregister.header.id = MESSAGE_REQ_AMF_COMPONENTREGISTER; + memcpy (&req_lib_amf_componentregister.compName, compName, sizeof (SaNameT)); + if (proxyCompName) { + memcpy (&req_lib_amf_componentregister.proxyCompName, proxyCompName, sizeof (SaNameT)); + } else { + memset (&req_lib_amf_componentregister.proxyCompName, 0, sizeof (SaNameT)); + } + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (amfInstance->fd, &req_lib_amf_componentregister, sizeof (struct req_lib_amf_componentregister), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + + /* + * Search for COMPONENTREGISTER responses and queue any + * messages that dont match in this handle's inq. + * This must be done to avoid dropping async messages + * during this sync message retrieval + */ + error = saRecvQueue (amfInstance->fd, &amfInstance->message, + &amfInstance->inq, MESSAGE_RES_AMF_COMPONENTREGISTER); + if (error != SA_OK) { + goto error_unlock; + } + + res_lib_amf_componentregister = (struct res_lib_amf_componentregister *)&amfInstance->message; + if (res_lib_amf_componentregister->error == SA_OK) { + amfInstance->compRegistered = 1; + memcpy (&amfInstance->compName, compName, sizeof (SaNameT)); + } + + error = res_lib_amf_componentregister->error; + +error_unlock: + pthread_mutex_unlock (&amfInstance->mutex); + return (error); +} + +SaErrorT +saAmfComponentUnregister ( + const SaAmfHandleT *amfHandle, + const SaNameT *compName, + const SaNameT *proxyCompName) +{ + struct req_lib_amf_componentunregister req_lib_amf_componentunregister; + struct res_lib_amf_componentunregister *res_lib_amf_componentunregister; + struct amfInstance *amfInstance; + SaErrorT error; + + req_lib_amf_componentunregister.header.magic = MESSAGE_MAGIC; + req_lib_amf_componentunregister.header.size = sizeof (struct req_lib_amf_componentunregister); + req_lib_amf_componentunregister.header.id = MESSAGE_REQ_AMF_COMPONENTUNREGISTER; + memcpy (&req_lib_amf_componentunregister.compName, compName, sizeof (SaNameT)); + if (proxyCompName) { + memcpy (&req_lib_amf_componentunregister.proxyCompName, proxyCompName, sizeof (SaNameT)); + } else { + memset (&req_lib_amf_componentunregister.proxyCompName, 0, sizeof (SaNameT)); + } + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (amfInstance->fd, &req_lib_amf_componentunregister, + sizeof (struct req_lib_amf_componentunregister), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + + /* + * Search for COMPONENTUNREGISTER responses and queue any + * messages that dont match in this handle's inq. + * This must be done to avoid dropping async messages + * during this sync message retrieval + */ + error = saRecvQueue (amfInstance->fd, &amfInstance->message, + &amfInstance->inq, MESSAGE_RES_AMF_COMPONENTUNREGISTER); + if (error != SA_OK) { + goto error_unlock; + } + res_lib_amf_componentunregister = (struct res_lib_amf_componentunregister *)&amfInstance->message; + if (res_lib_amf_componentunregister->error == SA_OK) { + amfInstance->compRegistered = 0; + } + error = res_lib_amf_componentunregister->error; + +error_unlock: + pthread_mutex_unlock (&amfInstance->mutex); + return (error); +} + +SaErrorT +saAmfCompNameGet ( + const SaAmfHandleT *amfHandle, + SaNameT *compName) +{ + struct amfInstance *amfInstance; + SaErrorT error; + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + if (amfInstance->compRegistered == 0) { + return (SA_ERR_NOT_EXIST); + } + memcpy (compName, &amfInstance->compName, sizeof (SaNameT)); + + pthread_mutex_unlock (&amfInstance->mutex); + return (SA_OK); +} + +SaErrorT +saAmfReadinessStateGet ( + const SaNameT *compName, + SaAmfReadinessStateT *readinessState) +{ + int fd; + SaErrorT error; + struct req_amf_readinessstateget req_amf_readinessstateget; + struct res_amf_readinessstateget *res_amf_readinessstateget; + struct message_overlay message; + + error = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (error != SA_OK) { + goto exit_noclose; + } + req_amf_readinessstateget.header.magic = MESSAGE_MAGIC; + req_amf_readinessstateget.header.id = MESSAGE_RES_AMF_READINESSSTATEGET; + req_amf_readinessstateget.header.size = sizeof (struct req_amf_readinessstateget); + memcpy (&req_amf_readinessstateget.compName, compName, sizeof (SaNameT)); + + error = saSendRetry (fd, &req_amf_readinessstateget, + sizeof (struct req_amf_readinessstateget), MSG_NOSIGNAL); + if (error != SA_OK) { + goto exit_close; + } + + error = saRecvQueue (fd, &message, 0, MESSAGE_RES_AMF_READINESSSTATEGET); + res_amf_readinessstateget = (struct res_amf_readinessstateget *)&message; + if (error == SA_OK) { + memcpy (readinessState, &res_amf_readinessstateget->readinessState, + sizeof (SaAmfReadinessStateT)); + error = res_amf_readinessstateget->error; + } + +exit_close: + close (fd); +exit_noclose: + return (error); +} + +SaErrorT +saAmfStoppingComplete ( + SaInvocationT invocation, + SaErrorT error) +{ + struct req_amf_stoppingcomplete req_amf_stoppingcomplete; + int fd; + SaErrorT errorResult; + + errorResult = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (errorResult != SA_OK) { + goto exit_noclose; + } + req_amf_stoppingcomplete.header.magic = MESSAGE_MAGIC; + req_amf_stoppingcomplete.header.id = MESSAGE_REQ_AMF_STOPPINGCOMPLETE; + req_amf_stoppingcomplete.header.size = sizeof (struct req_amf_stoppingcomplete); + req_amf_stoppingcomplete.invocation = invocation; + req_amf_stoppingcomplete.error = error; + errorResult = saSendRetry (fd, &req_amf_stoppingcomplete, + sizeof (struct req_amf_stoppingcomplete), MSG_NOSIGNAL); + + close (fd); + +exit_noclose: + return (errorResult); +} + +SaErrorT +saAmfHAStateGet ( + const SaNameT *compName, + const SaNameT *csiName, + SaAmfHAStateT *haState) { + + struct req_amf_hastateget req_amf_hastateget; + struct res_amf_hastateget *res_amf_hastateget; + int fd; + SaErrorT error; + struct message_overlay message; + + error = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (error != SA_OK) { + goto exit_noclose; + } + req_amf_hastateget.header.magic = MESSAGE_MAGIC; + req_amf_hastateget.header.id = MESSAGE_REQ_AMF_HASTATEGET; + req_amf_hastateget.header.size = sizeof (struct req_amf_hastateget); + memcpy (&req_amf_hastateget.compName, compName, sizeof (SaNameT)); + memcpy (&req_amf_hastateget.csiName, csiName, sizeof (SaNameT)); + + error = saSendRetry (fd, &req_amf_hastateget, + sizeof (struct req_amf_hastateget), MSG_NOSIGNAL); + if (error != SA_OK) { + goto exit_close; + } + + error = saRecvQueue (fd, &message, 0, MESSAGE_RES_AMF_HASTATEGET); + res_amf_hastateget = (struct res_amf_hastateget *)&message; + if (error != SA_OK) { + goto exit_close; + } + + error = res_amf_hastateget->error; + if (error == SA_OK) { + memcpy (haState, &res_amf_hastateget->haState, sizeof (SaAmfHAStateT)); + } + +exit_close: + close (fd); +exit_noclose: + return (error); +} + +SaErrorT +saAmfProtectionGroupTrackStart ( + const SaAmfHandleT *amfHandle, + const SaNameT *csiName, + SaUint8T trackFlags, + const SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems) { + + struct amfInstance *amfInstance; + struct req_amf_protectiongrouptrackstart req_amf_protectiongrouptrackstart; + struct res_amf_protectiongrouptrackstart *res_amf_protectiongrouptrackstart; + SaErrorT error; + + req_amf_protectiongrouptrackstart.header.magic = MESSAGE_MAGIC; + req_amf_protectiongrouptrackstart.header.size = sizeof (struct req_amf_protectiongrouptrackstart); + req_amf_protectiongrouptrackstart.header.id = MESSAGE_REQ_AMF_PROTECTIONGROUPTRACKSTART; + memcpy (&req_amf_protectiongrouptrackstart.csiName, csiName, sizeof (SaNameT)); + req_amf_protectiongrouptrackstart.trackFlags = trackFlags; + req_amf_protectiongrouptrackstart.notificationBufferAddress = (SaAmfProtectionGroupNotificationT *)notificationBuffer; + req_amf_protectiongrouptrackstart.numberOfItems = numberOfItems; + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (amfInstance->fd, &req_amf_protectiongrouptrackstart, + sizeof (struct req_amf_protectiongrouptrackstart), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + + error = saRecvQueue (amfInstance->fd, &amfInstance->message, + &amfInstance->inq, MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTART); + + pthread_mutex_unlock (&amfInstance->mutex); + + res_amf_protectiongrouptrackstart = (struct res_amf_protectiongrouptrackstart *)&amfInstance->message; + + if (error == SA_OK) { + return (res_amf_protectiongrouptrackstart->error); + } + + return (error); + +error_unlock: + pthread_mutex_unlock (&amfInstance->mutex); + + return (error); +} + +SaErrorT +saAmfProtectionGroupTrackStop ( + const SaAmfHandleT *amfHandle, + const SaNameT *csiName) { + + struct amfInstance *amfInstance; + struct req_amf_protectiongrouptrackstop req_amf_protectiongrouptrackstop; + struct res_amf_protectiongrouptrackstop *res_amf_protectiongrouptrackstop; + SaErrorT error; + + req_amf_protectiongrouptrackstop.header.magic = MESSAGE_MAGIC; + req_amf_protectiongrouptrackstop.header.size = sizeof (struct req_amf_protectiongrouptrackstop); + req_amf_protectiongrouptrackstop.header.id = MESSAGE_REQ_AMF_PROTECTIONGROUPTRACKSTOP; + memcpy (&req_amf_protectiongrouptrackstop.csiName, csiName, sizeof (SaNameT)); + + error = saHandleConvert (&amfHandleDatabase, *amfHandle, (void *)&amfInstance, AMFINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (amfInstance->fd, &req_amf_protectiongrouptrackstop, + sizeof (struct req_amf_protectiongrouptrackstop), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + + error = saRecvQueue (amfInstance->fd, &amfInstance->message, + &amfInstance->inq, MESSAGE_RES_AMF_PROTECTIONGROUPTRACKSTOP); + + pthread_mutex_unlock (&amfInstance->mutex); + + res_amf_protectiongrouptrackstop = (struct res_amf_protectiongrouptrackstop *)&amfInstance->message; + + if (error == SA_OK) { + return (res_amf_protectiongrouptrackstop->error); + } + + return (error); + +error_unlock: + pthread_mutex_unlock (&amfInstance->mutex); + return (error); +} + +SaErrorT +saAmfErrorReport ( + const SaNameT *reportingComponent, + const SaNameT *erroneousComponent, + SaTimeT errorDetectionTime, + const SaAmfErrorDescriptorT *errorDescriptor, + const SaAmfAdditionalDataT *additionalData) { + + struct req_lib_amf_errorreport req_lib_amf_errorreport; + struct res_lib_amf_errorreport *res_lib_amf_errorreport; + struct message_overlay message; + int fd; + SaErrorT error; + + error = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (error != SA_OK) { + goto exit_noclose; + } + req_lib_amf_errorreport.header.magic = MESSAGE_MAGIC; + req_lib_amf_errorreport.header.id = MESSAGE_REQ_AMF_ERRORREPORT; + req_lib_amf_errorreport.header.size = sizeof (struct req_lib_amf_errorreport); + memcpy (&req_lib_amf_errorreport.reportingComponent, reportingComponent, sizeof (SaNameT)); + memcpy (&req_lib_amf_errorreport.erroneousComponent, erroneousComponent, sizeof (SaNameT)); + req_lib_amf_errorreport.errorDetectionTime = errorDetectionTime; + memcpy (&req_lib_amf_errorreport.errorDescriptor, + errorDescriptor, sizeof (SaAmfErrorDescriptorT)); + /* TODO this is wrong, and needs some thinking + memcpy (&req_lib_amf_errorreport.additionalData, + additionalData, sizeof (SaAmfAdditionalDataT)); + */ + + error = saSendRetry (fd, &req_lib_amf_errorreport, + sizeof (struct req_lib_amf_errorreport), MSG_NOSIGNAL); + + /* + * Get response from executive and respond to user application + */ + error = saRecvQueue (fd, &message, 0, MESSAGE_RES_AMF_ERRORREPORT); + if (error != SA_OK) { + goto exit_close; + } + + res_lib_amf_errorreport = (struct res_lib_amf_errorreport *)&message; + error = res_lib_amf_errorreport->error; + +exit_close: + close (fd); +exit_noclose: + return (error); +} + +SaErrorT +saAmfErrorCancelAll ( + const SaNameT *compName) { + + struct req_lib_amf_errorcancelall req_lib_amf_errorcancelall; + struct res_lib_amf_errorcancelall *res_lib_amf_errorcancelall; + struct message_overlay message; + int fd; + SaErrorT error; + + error = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (error != SA_OK) { + goto exit_noclose; + } + req_lib_amf_errorcancelall.header.magic = MESSAGE_MAGIC; + req_lib_amf_errorcancelall.header.id = MESSAGE_REQ_AMF_ERRORCANCELALL; + req_lib_amf_errorcancelall.header.size = sizeof (struct req_lib_amf_errorcancelall); + memcpy (&req_lib_amf_errorcancelall.compName, compName, sizeof (SaNameT)); + + error = saSendRetry (fd, &req_lib_amf_errorcancelall, + sizeof (struct req_lib_amf_errorcancelall), MSG_NOSIGNAL); + + /* + * Get response from executive and respond to user application + */ + error = saRecvQueue (fd, &message, 0, MESSAGE_RES_AMF_ERRORCANCELALL); + if (error != SA_OK) { + goto exit_close; + } + + res_lib_amf_errorcancelall = (struct res_lib_amf_errorcancelall *)&message; + error = res_lib_amf_errorcancelall->error; + +exit_close: + close (fd); +exit_noclose: + return (error); +} + +SaErrorT +saAmfComponentCapabilityModelGet ( + const SaNameT *compName, + SaAmfComponentCapabilityModelT *componentCapabilityModel) +{ + + int fd; + SaErrorT error; + struct req_amf_componentcapabilitymodelget req_amf_componentcapabilitymodelget; + struct res_amf_componentcapabilitymodelget *res_amf_componentcapabilitymodelget; + struct message_overlay message; + + error = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (error != SA_OK) { + goto exit_noclose; + } + req_amf_componentcapabilitymodelget.header.magic = MESSAGE_MAGIC; + req_amf_componentcapabilitymodelget.header.id = MESSAGE_REQ_AMF_COMPONENTCAPABILITYMODELGET; + req_amf_componentcapabilitymodelget.header.size = sizeof (struct req_amf_componentcapabilitymodelget); + memcpy (&req_amf_componentcapabilitymodelget.compName, compName, sizeof (SaNameT)); + + error = saSendRetry (fd, &req_amf_componentcapabilitymodelget, + sizeof (struct req_amf_componentcapabilitymodelget), MSG_NOSIGNAL); + if (error != SA_OK) { + goto exit_close; + } + + error = saRecvQueue (fd, &message, 0, MESSAGE_RES_AMF_COMPONENTCAPABILITYMODELGET); + res_amf_componentcapabilitymodelget = (struct res_amf_componentcapabilitymodelget *)&message; + if (error == SA_OK) { + memcpy (componentCapabilityModel, + &res_amf_componentcapabilitymodelget->componentCapabilityModel, + sizeof (SaAmfComponentCapabilityModelT)); + error = res_amf_componentcapabilitymodelget->error; + } + +exit_close: + close (fd); +exit_noclose: + return (error); +} + +SaErrorT +saAmfPendingOperationGet ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT *pendingOperationFlags) { + + *pendingOperationFlags = 0; + return (SA_OK); +} + +SaErrorT +saAmfResponse ( + SaInvocationT invocation, + SaErrorT error) +{ + struct req_amf_response req_amf_response; + int fd; + SaErrorT errorResult; + + errorResult = saServiceConnect (&fd, MESSAGE_REQ_AMF_INIT); + if (errorResult != SA_OK) { + goto exit_noclose; + } + req_amf_response.header.magic = MESSAGE_MAGIC; + req_amf_response.header.id = MESSAGE_REQ_AMF_RESPONSE; + req_amf_response.header.size = sizeof (struct req_amf_response); + req_amf_response.invocation = invocation; + req_amf_response.error = error; + errorResult = saSendRetry (fd, &req_amf_response, + sizeof (struct req_amf_response), MSG_NOSIGNAL); + + close (fd); + +exit_noclose: + return (errorResult); +} diff --git a/lib/ckpt.c b/lib/ckpt.c index e69de29b..aa46978d 100644 --- a/lib/ckpt.c +++ b/lib/ckpt.c @@ -0,0 +1,1251 @@ + +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/list.h" +#include "../include/ais_types.h" +#include "../include/ais_ckpt.h" +#include "../include/ais_msg.h" +#include "util.h" + +struct message_overlay { + struct message_header header; + char data[4096]; +}; + +/* + * Data structure for instance data + */ +struct ckptInstance { + int fd; + struct queue inq; + SaCkptCallbacksT callbacks; + pthread_mutex_t mutex; +}; +#define CKPTINSTANCE_MUTEX_OFFSET HANDLECONVERT_NOLOCKING + +struct ckptCheckpointInstance { + int fd; + SaNameT checkpointName; + SaUint32T maxSectionIdSize; + pthread_mutex_t mutex; +}; +//#define CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET offset_of(struct ckptCheckpointInstance, mutex) +#define CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET_DEMO offset_of(struct ckptCheckpointInstance, mutex) +#define CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET HANDLECONVERT_NOLOCKING + +struct ckptSectionIteratorInstance { + int fd; + struct list_head sectionIdListHead; + SaUint32T maxSectionIdSize; + pthread_mutex_t mutex; +}; + +//#define CKPTSECTIONITERATORINSTANCE_MUTEX_OFFSET offset_of(struct ckptSectionIteratorInstance, mutex) +#define CKPTSECTIONITERATORINSTANCE_MUTEX_OFFSET HANDLECONVERT_NOLOCKING + +/* + * All CKPT instances in this database + */ +static struct saHandleDatabase ckptHandleDatabase = { + handleCount: 0, + handles: 0, + generation: 0, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +/* + * All Checkpoint instances in this database + */ +static struct saHandleDatabase ckptCheckpointHandleDatabase = { + handleCount: 0, + handles: 0, + generation: 0, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +/* + * All section iterators in this database + */ +static struct saHandleDatabase ckptSectionIteratorHandleDatabase = { + handleCount: 0, + handles: 0, + generation: 0, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +/* + * Versions supported + */ +static SaVersionT ckptVersionsSupported[] = { + { 'A', 1, 1 }, + { 'a', 1, 1 } +}; + +static struct saVersionDatabase ckptVersionDatabase = { + sizeof (ckptVersionsSupported) / sizeof (SaVersionT), + ckptVersionsSupported +}; + + +//static struct timeval zerousec = { +// 0, 0 +//}; + +/* + * Implementation + */ +SaErrorT +saCkptInitialize ( + SaCkptHandleT *ckptHandle, + const SaCkptCallbacksT *callbacks, + const SaVersionT *version) +{ + struct ckptInstance *ckptInstance; + SaErrorT error = SA_OK; + + error = saVersionVerify (&ckptVersionDatabase, version); + if (error != SA_OK) { + goto error_nofree; + } + + error = saHandleCreate (&ckptHandleDatabase, (void *)&ckptInstance, + sizeof (struct ckptInstance), ckptHandle); + if (error != SA_OK) { + goto error_nofree; + } + + /* + * An inq is needed to store async messages while waiting for a + * sync response + */ + error = saQueueInit (&ckptInstance->inq, 512, sizeof (void *)); + if (error != SA_OK) { + goto error_free; + } + + error = saServiceConnect (&ckptInstance->fd, MESSAGE_REQ_CKPT_CHECKPOINT_INIT); + if (error != SA_OK) { + goto error_free2; + } + + memcpy (&ckptInstance->callbacks, callbacks, sizeof (SaCkptCallbacksT)); + + pthread_mutex_init (&ckptInstance->mutex, NULL); + + return (SA_OK); +error_free2: + free (ckptInstance->inq.items); +error_free: + saHandleRemove (&ckptHandleDatabase, *ckptHandle); +error_nofree: + return (error); +} + +SaErrorT +saCkptSelectionObjectGet ( + const SaCkptHandleT *ckptHandle, + SaSelectionObjectT *selectionObject) +{ + struct ckptInstance *ckptInstance; + SaErrorT error; + + error = saHandleConvert (&ckptHandleDatabase, *ckptHandle, (void *)&ckptInstance, CKPTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + *selectionObject = ckptInstance->fd; + return (SA_OK); +} + +#ifdef COMPILE_OUT +SaErrorT +saCkptDispatch ( + const SaCkptHandleT *ckptHandle, + SaDispatchFlagsT dispatchFlags) +{ + fd_set read_fds; + SaErrorT error; + int dispatch_avail; + struct timeval *timeout = 0; + struct ckptInstance *ckptInstance; + struct message_header **queue_msg; + struct message_header *msg; + int empty; + int ignore_dispatch = 0; + int cont = 1; /* always continue do loop except when set to 0 */ + + error = saHandleConvert (&ckptHandleDatabase, *ckptHandle, (void *)&ckptInstance, CKPTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + /* + * Timeout instantly for SA_DISPATCH_ALL + */ + if (dispatchFlags & SA_DISPATCH_ALL) { + timeout = &zerousec; + } + + do { + /* + * Read data directly from socket + */ + FD_ZERO (&read_fds); + FD_SET (ckptInstance->fd, &read_fds); + + error = saSelectRetry (ckptInstance->fd + 1, &read_fds, 0, 0, timeout); + if (error != SA_OK) { + goto error_exit; + } + + dispatch_avail = FD_ISSET (ckptInstance->fd, &read_fds); + if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) { + break; /* exit do while cont is 1 loop */ + } else + if (dispatch_avail == 0) { + continue; /* next select */ + } + + saQueueIsEmpty(&ckptInstance->inq, &empty); + if (empty == 0) { + /* + * Queue is not empty, read data from queue + */ + saQueueItemGet (&ckptInstance->inq, (void **)&queue_msg); + msg = *queue_msg; + memcpy (&ckptInstance->message, msg, msg->size); + saQueueItemRemove (&ckptInstance->inq); + } else { + /* + * Queue empty, read response from socket + */ + error = saRecvRetry (ckptInstance->fd, &ckptInstance->message.header, sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + if (ckptInstance->message.header.size > sizeof (struct message_header)) { + error = saRecvRetry (ckptInstance->fd, &ckptInstance->message.data, + ckptInstance->message.header.size - sizeof (struct message_header), + MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + } + } + + /* + * Dispatch incoming response + */ + switch (ckptInstance->message.header.id) { +#ifdef COMPILE_OUT + case MESSAGE_RES_CKPT_CHECKPOINT_ACTIVATEPOLL: + /* + * This is a do nothing message which the node executive sends + * to activate the file handle in poll when the library has + * queued a message into amfHandle->inq + * The dispatch is ignored for the following two cases: + * 1) setting of timeout to zero for the DISPATCH_ALL case + * 2) expiration of the do loop for the DISPATCH_ONE case + */ + ignore_dispatch = 1; + break; + + case MESSAGE_RES_CKPT_CHECKPOINT_HEALTHCHECKCALLBACK: + res_amf_healthcheckcallback = (struct res_amf_healthcheckcallback *)&ckptInstance->message; + amfInstance->callbacks.saAmfHealthcheckCallback ( + res_amf_healthcheckcallback->invocation, + &res_amf_healthcheckcallback->compName, + res_amf_healthcheckcallback->checkType); + break; + + case MESSAGE_RES_CKPT_CHECKPOINT_READINESSSTATESETCALLBACK: + res_amf_readinessstatesetcallback = (struct res_amf_readinessstatesetcallback *)&ckptInstance->message; + amfInstance->callbacks.saAmfReadinessStateSetCallback ( + res_amf_readinessstatesetcallback->invocation, + &res_amf_readinessstatesetcallback->compName, + res_amf_readinessstatesetcallback->readinessState); + break; + + case MESSAGE_RES_CKPT_CHECKPOINT_CSISETCALLBACK: + res_amf_csisetcallback = (struct res_amf_csisetcallback *)&ckptInstance->message; + amfInstance->callbacks.saAmfCSISetCallback ( + res_amf_csisetcallback->invocation, + &res_amf_csisetcallback->compName, + &res_amf_csisetcallback->csiName, + res_amf_csisetcallback->csiFlags, + &res_amf_csisetcallback->haState, + &res_amf_csisetcallback->activeCompName, + res_amf_csisetcallback->transitionDescriptor); + break; + + case MESSAGE_RES_CKPT_CHECKPOINT_CSIREMOVECALLBACK: + res_amf_csiremovecallback = (struct res_amf_csiremovecallback *)&ckptInstance->message; + amfInstance->callbacks.saAmfCSIRemoveCallback ( + res_amf_csiremovecallback->invocation, + &res_amf_csiremovecallback->compName, + &res_amf_csiremovecallback->csiName, + &res_amf_csiremovecallback->csiFlags); + break; + + case MESSAGE_RES_CKPT_CHECKPOINT_PROTECTIONGROUPTRACKCALLBACK: + res_amf_protectiongrouptrackcallback = (struct res_amf_protectiongrouptrackcallback *)&ckptInstance->message; + memcpy (res_amf_protectiongrouptrackcallback->notificationBufferAddress, + res_amf_protectiongrouptrackcallback->notificationBuffer, + res_amf_protectiongrouptrackcallback->numberOfItems * sizeof (SaAmfProtectionGroupNotificationT)); + amfInstance->callbacks.saAmfProtectionGroupTrackCallback( + &res_amf_protectiongrouptrackcallback->csiName, + res_amf_protectiongrouptrackcallback->notificationBufferAddress, + res_amf_protectiongrouptrackcallback->numberOfItems, + res_amf_protectiongrouptrackcallback->numberOfMembers, + res_amf_protectiongrouptrackcallback->error); + break; + +#endif + default: + // TODO + break; + } + /* + * Determine if more messages should be processed + */ + switch (dispatchFlags) { + case SA_DISPATCH_ONE: + if (ignore_dispatch) { + ignore_dispatch = 0; + } else { + cont = 0; + } + break; + case SA_DISPATCH_ALL: + if (ignore_dispatch) { + ignore_dispatch = 0; + } + break; + case SA_DISPATCH_BLOCKING: + break; + } + } while (cont); + +error_exit: + return (error); +} +#endif + +SaErrorT +saCkptFinalize ( + const SaCkptHandleT *ckptHandle) +{ + struct ckptInstance *ckptInstance; + SaErrorT error; + + error = saHandleConvert (&ckptHandleDatabase, *ckptHandle, (void *)&ckptInstance, CKPTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + close (ckptInstance->fd); + free (ckptInstance->inq.items); + saHandleRemove (&ckptHandleDatabase, *ckptHandle); + return (SA_OK); +} + +SaErrorT +saCkptCheckpointOpen ( + const SaNameT *checkpointName, + const SaCkptCheckpointCreationAttributesT *checkpointCreationAttributes, + SaCkptCheckpointOpenFlagsT checkpointOpenFlags, + SaTimeT timeout, + SaCkptCheckpointHandleT *checkpointHandle) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_checkpointopen req_lib_ckpt_checkpointopen; + struct res_lib_ckpt_checkpointopen res_lib_ckpt_checkpointopen; + + error = saHandleCreate (&ckptCheckpointHandleDatabase, (void *)&ckptCheckpointInstance, + sizeof (struct ckptCheckpointInstance), checkpointHandle); + if (error != SA_OK) { + goto error_nofree; + } + + ckptCheckpointInstance->maxSectionIdSize = + checkpointCreationAttributes->maxSectionIdSize; + + error = saServiceConnect (&ckptCheckpointInstance->fd, MESSAGE_REQ_CKPT_CHECKPOINT_INIT); + if (error != SA_OK) { + goto error_free; + } + + pthread_mutex_init (&ckptCheckpointInstance->mutex, NULL); + + req_lib_ckpt_checkpointopen.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointopen.header.size = sizeof (struct req_lib_ckpt_checkpointopen); + req_lib_ckpt_checkpointopen.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTOPEN; + memcpy (&req_lib_ckpt_checkpointopen.checkpointName, checkpointName, sizeof (SaNameT)); + memcpy (&ckptCheckpointInstance->checkpointName, checkpointName, sizeof (SaNameT)); + memcpy (&req_lib_ckpt_checkpointopen.checkpointCreationAttributes, + checkpointCreationAttributes, + sizeof (SaCkptCheckpointCreationAttributesT)); + req_lib_ckpt_checkpointopen.checkpointOpenFlags = checkpointOpenFlags; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_checkpointopen, + sizeof (struct req_lib_ckpt_checkpointopen), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_close; + } + + error = saRecvRetry (ckptCheckpointInstance->fd, &res_lib_ckpt_checkpointopen, + sizeof (struct res_lib_ckpt_checkpointopen), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_close; + } + + if (res_lib_ckpt_checkpointopen.error != SA_OK) { + error = res_lib_ckpt_checkpointopen.error; + goto error_close; + } + + pthread_mutex_init (&ckptCheckpointInstance->mutex, NULL); + +error_nofree: + return (error); +error_close: + close (ckptCheckpointInstance->fd); +error_free: + saHandleRemove (&ckptCheckpointHandleDatabase, *checkpointHandle); + return (error); +} + +SaErrorT +saCkptCheckpointOpenAsync ( + const SaCkptHandleT *ckptHandle, + SaInvocationT invocation, + const SaNameT *checkpointName, + const SaCkptCheckpointCreationAttributesT *checkpointCreationAttributes, + SaCkptCheckpointOpenFlagsT checkpointOpenFlags) +{ + struct ckptInstance *ckptInstance; + SaErrorT error; + struct req_lib_ckpt_checkpointopenasync req_lib_ckpt_checkpointopenasync; + + error = saHandleConvert (&ckptHandleDatabase, *ckptHandle, (void *)&ckptInstance, CKPTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + req_lib_ckpt_checkpointopenasync.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointopenasync.header.size = sizeof (struct req_lib_ckpt_checkpointopenasync); + req_lib_ckpt_checkpointopenasync.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTOPENASYNC; + req_lib_ckpt_checkpointopenasync.invocation = invocation; + memcpy (&req_lib_ckpt_checkpointopenasync.checkpointName, checkpointName, sizeof (SaNameT)); + memcpy (&req_lib_ckpt_checkpointopenasync.checkpointCreationAttributes, + checkpointCreationAttributes, + sizeof (SaCkptCheckpointCreationAttributesT)); + + req_lib_ckpt_checkpointopenasync.checkpointOpenFlags = checkpointOpenFlags; + + error = saSendRetry (ckptInstance->fd, &req_lib_ckpt_checkpointopenasync, + sizeof (struct req_lib_ckpt_checkpointopenasync), MSG_NOSIGNAL); + + return (error); +} + +SaErrorT +saCkptCheckpointClose ( + const SaCkptCheckpointHandleT *checkpointHandle) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + close (ckptCheckpointInstance->fd); + error = saHandleRemove (&ckptCheckpointHandleDatabase, *checkpointHandle); + +error_exit: + return (error); +} + +SaErrorT +saCkptCheckpointUnlink ( + const SaNameT *checkpointName) +{ + SaErrorT error; + struct req_lib_ckpt_checkpointunlink req_lib_ckpt_checkpointunlink; + struct res_lib_ckpt_checkpointunlink res_lib_ckpt_checkpointunlink; + int fd; + + error = saServiceConnect (&fd, MESSAGE_REQ_CKPT_CHECKPOINT_INIT); + if (error != SA_OK) { + goto exit_noclose; + } + + req_lib_ckpt_checkpointunlink.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointunlink.header.size = sizeof (struct req_lib_ckpt_checkpointunlink); + req_lib_ckpt_checkpointunlink.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTUNLINK; + memcpy (&req_lib_ckpt_checkpointunlink.checkpointName, checkpointName, sizeof (SaNameT)); + + + error = saSendRetry (fd, &req_lib_ckpt_checkpointunlink, sizeof (struct req_lib_ckpt_checkpointunlink), MSG_NOSIGNAL); + if (error != SA_OK) { + goto exit_close; + } + + error = saRecvQueue (fd, &res_lib_ckpt_checkpointunlink, + 0, MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTUNLINK); + +exit_close: + close (fd); + return (error == SA_OK ? res_lib_ckpt_checkpointunlink.error : error); +exit_noclose: + return (error); +} + +SaErrorT +saCkptCheckpointRetentionDurationSet ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaTimeT retentionDuration) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_checkpointretentiondurationset req_lib_ckpt_checkpointretentiondurationset; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_checkpointretentiondurationset.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointretentiondurationset.header.size = sizeof (struct req_lib_ckpt_checkpointretentiondurationset); + req_lib_ckpt_checkpointretentiondurationset.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTRETENTIONDURATIONSET; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_checkpointretentiondurationset, sizeof (struct req_lib_ckpt_checkpointretentiondurationset), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + +error_exit: + return (error); +} + +SaErrorT +saCkptActiveCheckpointSet ( + const SaCkptCheckpointHandleT *checkpointHandle) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_activecheckpointset req_lib_ckpt_activecheckpointset; + struct res_lib_ckpt_activecheckpointset res_lib_ckpt_activecheckpointset; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_activecheckpointset.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_activecheckpointset.header.size = sizeof (struct req_lib_ckpt_activecheckpointset); + req_lib_ckpt_activecheckpointset.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_ACTIVECHECKPOINTSET; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_activecheckpointset, + sizeof (struct req_lib_ckpt_activecheckpointset), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + error = saRecvQueue (ckptCheckpointInstance->fd, &res_lib_ckpt_activecheckpointset, 0, MESSAGE_RES_CKPT_CHECKPOINT_ACTIVECHECKPOINTSET); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_activecheckpointset.error : error); +} + +SaErrorT +saCkptCheckpointStatusGet ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptCheckpointStatusT *checkpointStatus) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_checkpointstatusget req_lib_ckpt_checkpointstatusget; + struct res_lib_ckpt_checkpointstatusget res_lib_ckpt_checkpointstatusget; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_checkpointstatusget.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointstatusget.header.size = sizeof (struct req_lib_ckpt_checkpointstatusget); + req_lib_ckpt_checkpointstatusget.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTSTATUSGET; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_checkpointstatusget, + sizeof (struct req_lib_ckpt_checkpointstatusget), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + error = saRecvQueue (ckptCheckpointInstance->fd, &res_lib_ckpt_checkpointstatusget, + 0, MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSTATUSGET); + if (error != SA_OK) { + goto error_exit; + } + + memcpy (checkpointStatus, + &res_lib_ckpt_checkpointstatusget.checkpointStatus, + sizeof (SaCkptCheckpointStatusT)); + +error_exit: + return (error); +} + +SaErrorT +saCkptSectionCreate ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptSectionCreationAttributesT *sectionCreationAttributes, + const void *initialData, + SaUint32T initialDataSize) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_sectioncreate req_lib_ckpt_sectioncreate; + struct res_lib_ckpt_sectioncreate res_lib_ckpt_sectioncreate; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_sectioncreate.header.magic = MESSAGE_MAGIC; + + req_lib_ckpt_sectioncreate.header.size = + sizeof (struct req_lib_ckpt_sectioncreate) + + sectionCreationAttributes->sectionId->idLen + + initialDataSize; + + req_lib_ckpt_sectioncreate.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONCREATE; + req_lib_ckpt_sectioncreate.idLen = sectionCreationAttributes->sectionId->idLen; + req_lib_ckpt_sectioncreate.expirationTime = sectionCreationAttributes->expirationTime; + req_lib_ckpt_sectioncreate.initialDataSize = initialDataSize; + + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_sectioncreate, + sizeof (struct req_lib_ckpt_sectioncreate), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + /* + * Write section identifier to server + */ + error = saSendRetry (ckptCheckpointInstance->fd, sectionCreationAttributes->sectionId->id, + sectionCreationAttributes->sectionId->idLen, MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + error = saSendRetry (ckptCheckpointInstance->fd, initialData, + initialDataSize, MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + error = saRecvQueue (ckptCheckpointInstance->fd, &res_lib_ckpt_sectioncreate, 0, MESSAGE_RES_CKPT_CHECKPOINT_SECTIONCREATE); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_sectioncreate.error : error); +} + + +SaErrorT +saCkptSectionDelete ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptSectionIdT *sectionId) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_sectiondelete req_lib_ckpt_sectiondelete; + struct res_lib_ckpt_sectiondelete res_lib_ckpt_sectiondelete; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_sectiondelete.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectiondelete.header.size = sizeof (struct req_lib_ckpt_sectiondelete) + sectionId->idLen; + req_lib_ckpt_sectiondelete.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONDELETE; + req_lib_ckpt_sectiondelete.idLen = sectionId->idLen; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_sectiondelete, + sizeof (struct req_lib_ckpt_sectiondelete), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + /* + * Write section identifier to server + */ + error = saSendRetry (ckptCheckpointInstance->fd, sectionId->id, + sectionId->idLen, MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + error = saRecvQueue (ckptCheckpointInstance->fd, &res_lib_ckpt_sectiondelete, 0, MESSAGE_RES_CKPT_CHECKPOINT_SECTIONDELETE); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_sectiondelete.error : error); +} + +SaErrorT +saCkptSectionExpirationTimeSet ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptSectionIdT *sectionId, + SaTimeT expirationTime) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_sectionexpirationtimeset req_lib_ckpt_sectionexpirationtimeset; + struct res_lib_ckpt_sectionexpirationtimeset res_lib_ckpt_sectionexpirationtimeset; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_sectionexpirationtimeset.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectionexpirationtimeset.header.size = sizeof (struct req_lib_ckpt_sectionexpirationtimeset) + sectionId->idLen; + req_lib_ckpt_sectionexpirationtimeset.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONEXPIRATIONTIMESET; + req_lib_ckpt_sectionexpirationtimeset.idLen = sectionId->idLen; + req_lib_ckpt_sectionexpirationtimeset.expirationTime = expirationTime; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_sectionexpirationtimeset, + sizeof (struct req_lib_ckpt_sectionexpirationtimeset), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + /* + * Write section identifier to server + */ + if (sectionId->idLen) { + error = saSendRetry (ckptCheckpointInstance->fd, sectionId->id, + sectionId->idLen, MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + } + + error = saRecvQueue (ckptCheckpointInstance->fd, &res_lib_ckpt_sectionexpirationtimeset, + 0, MESSAGE_RES_CKPT_CHECKPOINT_SECTIONEXPIRATIONTIMESET); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_sectionexpirationtimeset.error : error); +} + +SaErrorT +saCkptSectionIteratorInitialize ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptSectionsChosenT sectionsChosen, + SaTimeT expirationTime, + SaCkptSectionIteratorT *sectionIterator) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct ckptSectionIteratorInstance *ckptSectionIteratorInstance; + struct req_lib_ckpt_sectioniteratorinitialize req_lib_ckpt_sectioniteratorinitialize; + struct res_lib_ckpt_sectioniteratorinitialize res_lib_ckpt_sectioniteratorinitialize; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + error = saHandleCreate (&ckptSectionIteratorHandleDatabase, + (void *)&ckptSectionIteratorInstance, + sizeof (struct ckptSectionIteratorInstance), sectionIterator); + if (error != SA_OK) { + goto error_exit; + } + /* + * Setup section id list for iterator next + */ + list_init (&ckptSectionIteratorInstance->sectionIdListHead); + + ckptSectionIteratorInstance->maxSectionIdSize = + ckptCheckpointInstance->maxSectionIdSize; + + error = saServiceConnect (&ckptSectionIteratorInstance->fd, + MESSAGE_REQ_CKPT_SECTIONITERATOR_INIT); + if (error != SA_OK) { + goto error_remove; + } + + pthread_mutex_init (&ckptSectionIteratorInstance->mutex, NULL); + + req_lib_ckpt_sectioniteratorinitialize.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectioniteratorinitialize.header.size = sizeof (struct req_lib_ckpt_sectioniteratorinitialize); + req_lib_ckpt_sectioniteratorinitialize.header.id = MESSAGE_REQ_CKPT_SECTIONITERATOR_SECTIONITERATORINITIALIZE; + req_lib_ckpt_sectioniteratorinitialize.sectionsChosen = sectionsChosen; + req_lib_ckpt_sectioniteratorinitialize.expirationTime = expirationTime; + memcpy (&req_lib_ckpt_sectioniteratorinitialize.checkpointName, + &ckptCheckpointInstance->checkpointName, sizeof (SaNameT)); + + error = saSendRetry (ckptSectionIteratorInstance->fd, + &req_lib_ckpt_sectioniteratorinitialize, sizeof (struct req_lib_ckpt_sectioniteratorinitialize), MSG_NOSIGNAL); + + if (error != SA_OK) { + goto error_close; + } + + error = saRecvQueue (ckptSectionIteratorInstance->fd, + &res_lib_ckpt_sectioniteratorinitialize, 0, + MESSAGE_RES_CKPT_SECTIONITERATOR_SECTIONITERATORINITIALIZE); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_sectioniteratorinitialize.error : error); +error_close: + close (ckptSectionIteratorInstance->fd); +error_remove: + saHandleRemove (&ckptSectionIteratorHandleDatabase, *sectionIterator); + return (error); +} + +struct iteratorSectionIdListEntry { + struct list_head list; + char data[0]; +}; + +SaErrorT +saCkptSectionIteratorNext ( + SaCkptSectionIteratorT *sectionIterator, + SaCkptSectionDescriptorT *sectionDescriptor) +{ + SaErrorT error; + struct ckptSectionIteratorInstance *ckptSectionIteratorInstance; + struct req_lib_ckpt_sectioniteratornext req_lib_ckpt_sectioniteratornext; + struct res_lib_ckpt_sectioniteratornext res_lib_ckpt_sectioniteratornext; + struct iteratorSectionIdListEntry *iteratorSectionIdListEntry; + + error = saHandleConvert (&ckptSectionIteratorHandleDatabase, *sectionIterator, + (void *)&ckptSectionIteratorInstance, + CKPTSECTIONITERATORINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + /* + * Allocate section id storage area + */ + iteratorSectionIdListEntry = malloc (sizeof (struct list_head) + + ckptSectionIteratorInstance->maxSectionIdSize); + if (iteratorSectionIdListEntry == 0) { + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + + req_lib_ckpt_sectioniteratornext.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectioniteratornext.header.size = sizeof (struct req_lib_ckpt_sectioniteratornext); + req_lib_ckpt_sectioniteratornext.header.id = MESSAGE_REQ_CKPT_SECTIONITERATOR_SECTIONITERATORNEXT; + + error = saSendRetry (ckptSectionIteratorInstance->fd, + &req_lib_ckpt_sectioniteratornext, + sizeof (struct req_lib_ckpt_sectioniteratornext), MSG_NOSIGNAL); + + if (error != SA_OK) { + goto error_exit; + } + + error = saRecvRetry (ckptSectionIteratorInstance->fd, &res_lib_ckpt_sectioniteratornext, + sizeof (struct res_lib_ckpt_sectioniteratornext), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + memcpy (sectionDescriptor, + &res_lib_ckpt_sectioniteratornext.sectionDescriptor, + sizeof (SaCkptSectionDescriptorT)); + + sectionDescriptor->sectionId.id = &iteratorSectionIdListEntry->data[0]; + + if ((res_lib_ckpt_sectioniteratornext.header.size - sizeof (struct res_lib_ckpt_sectioniteratornext)) > 0) { + error = saRecvRetry (ckptSectionIteratorInstance->fd, + sectionDescriptor->sectionId.id, + res_lib_ckpt_sectioniteratornext.header.size - + sizeof (struct res_lib_ckpt_sectioniteratornext), + MSG_WAITALL | MSG_NOSIGNAL); + } + + /* + * Add to persistent memory list for this sectioniterator + */ + if (error == SA_OK && res_lib_ckpt_sectioniteratornext.error == SA_OK) { + list_init (&iteratorSectionIdListEntry->list); + list_add (&iteratorSectionIdListEntry->list, &ckptSectionIteratorInstance->sectionIdListHead); + } + +error_exit: + return (error == SA_OK ? res_lib_ckpt_sectioniteratornext.error : error); +} + +SaErrorT +saCkptSectionIteratorFinalize ( + SaCkptSectionIteratorT *sectionIterator) +{ + SaErrorT error; + struct ckptSectionIteratorInstance *ckptSectionIteratorInstance; + struct iteratorSectionIdListEntry *iteratorSectionIdListEntry; + struct list_head *sectionIdIteratorList; + struct list_head *sectionIdIteratorListNext; + + error = saHandleConvert (&ckptSectionIteratorHandleDatabase, *sectionIterator, + (void *)&ckptSectionIteratorInstance, + CKPTSECTIONITERATORINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + close (ckptSectionIteratorInstance->fd); + + /* + * iterate list of section ids for this iterator to free the allocated memory + * be careful to cache next pointer because free removes memory from use + */ + for (sectionIdIteratorList = ckptSectionIteratorInstance->sectionIdListHead.next, + sectionIdIteratorListNext = sectionIdIteratorList->next; + sectionIdIteratorList != &ckptSectionIteratorInstance->sectionIdListHead; + sectionIdIteratorList = sectionIdIteratorListNext, + sectionIdIteratorListNext = sectionIdIteratorList->next) { + + iteratorSectionIdListEntry = list_entry (sectionIdIteratorList, + struct iteratorSectionIdListEntry, list); + + free (iteratorSectionIdListEntry); + } + + saHandleRemove (&ckptSectionIteratorHandleDatabase, *sectionIterator); + +error_exit: + return (error); +} + +SaErrorT +saCkptCheckpointWrite ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptIOVectorElementT *ioVector, + SaUint32T numberOfElements, + SaUint32T *erroneousVectorIndex) +{ + SaErrorT error = SA_OK; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_sectionwrite req_lib_ckpt_sectionwrite; + struct res_lib_ckpt_sectionwrite res_lib_ckpt_sectionwrite; + int i; + struct iovec iov[3]; + int iov_len = 0; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET_DEMO, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_sectionwrite.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectionwrite.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONWRITE; + + + for (i = 0; i < numberOfElements; i++) { + + req_lib_ckpt_sectionwrite.header.size = sizeof (struct req_lib_ckpt_sectionwrite) + ioVector[i].sectionId.idLen + ioVector[i].dataSize; + + req_lib_ckpt_sectionwrite.dataOffset = ioVector[i].dataOffset; + req_lib_ckpt_sectionwrite.dataSize = ioVector[i].dataSize; + req_lib_ckpt_sectionwrite.idLen = ioVector[i].sectionId.idLen; + + iov_len = 0; +// TODO check for zero length stuff + iov[0].iov_base = &req_lib_ckpt_sectionwrite; + iov[0].iov_len = sizeof (struct req_lib_ckpt_sectionwrite); + iov[1].iov_base = ioVector[i].sectionId.id; + iov[1].iov_len = ioVector[i].sectionId.idLen; + iov[2].iov_base = ioVector[i].dataBuffer; + iov[2].iov_len = ioVector[i].dataSize; + + error = saSendMsgRetry (ckptCheckpointInstance->fd, + iov, + 3); + if (error != SA_OK) { + goto error_exit; + } + + /* + * Receive response + */ + error = saRecvRetry (ckptCheckpointInstance->fd, &res_lib_ckpt_sectionwrite, + sizeof (struct res_lib_ckpt_sectionwrite), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + /* + * If error, report back erroneous index + */ + if (res_lib_ckpt_sectionwrite.error != SA_OK) { + if (erroneousVectorIndex) { + *erroneousVectorIndex = i; + } + goto error_exit; + } + } + +error_exit: + pthread_mutex_unlock (&ckptCheckpointInstance->mutex); + return (error == SA_OK ? res_lib_ckpt_sectionwrite.error : error); +} + +SaErrorT +saCkptSectionOverwrite ( + const SaCkptCheckpointHandleT *checkpointHandle, + const SaCkptSectionIdT *sectionId, + SaUint8T *dataBuffer, + SaSizeT dataSize) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_sectionoverwrite req_lib_ckpt_sectionoverwrite; + struct res_lib_ckpt_sectionoverwrite res_lib_ckpt_sectionoverwrite; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_sectionoverwrite.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectionoverwrite.header.size = sizeof (struct req_lib_ckpt_sectionoverwrite) + sectionId->idLen + dataSize; + req_lib_ckpt_sectionoverwrite.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONOVERWRITE; + req_lib_ckpt_sectionoverwrite.idLen = sectionId->idLen; + req_lib_ckpt_sectionoverwrite.dataSize = dataSize; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_sectionoverwrite, + sizeof (struct req_lib_ckpt_sectionoverwrite), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + if (sectionId->idLen) { + error = saSendRetry (ckptCheckpointInstance->fd, sectionId->id, + sectionId->idLen, MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + } + error = saSendRetry (ckptCheckpointInstance->fd, dataBuffer, dataSize, MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + error = saRecvQueue (ckptCheckpointInstance->fd, + &res_lib_ckpt_sectionoverwrite, 0, MESSAGE_RES_CKPT_CHECKPOINT_SECTIONOVERWRITE); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_sectionoverwrite.error : error); +} + +SaErrorT +saCkptCheckpointRead ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaCkptIOVectorElementT *ioVector, + SaUint32T numberOfElements, + SaUint32T *erroneousVectorIndex) +{ + SaErrorT error = SA_OK; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_sectionread req_lib_ckpt_sectionread; + struct res_lib_ckpt_sectionread res_lib_ckpt_sectionread; + int dataLength; + int i; + struct iovec iov[3]; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET_DEMO, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_sectionread.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_sectionread.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_SECTIONREAD; + + for (i = 0; i < numberOfElements; i++) { + req_lib_ckpt_sectionread.header.size = sizeof (struct req_lib_ckpt_sectionread) + + ioVector[i].sectionId.idLen; + + req_lib_ckpt_sectionread.idLen = ioVector[i].sectionId.idLen; + req_lib_ckpt_sectionread.dataOffset = ioVector[i].dataOffset; + req_lib_ckpt_sectionread.dataSize = ioVector[i].dataSize; + + iov[0].iov_base = &req_lib_ckpt_sectionread; + iov[0].iov_len = sizeof (struct req_lib_ckpt_sectionread); + iov[1].iov_base = ioVector[i].sectionId.id; + iov[1].iov_len = ioVector[i].sectionId.idLen; + + error = saSendMsgRetry (ckptCheckpointInstance->fd, + iov, + 2); + + /* + * Receive response header + */ + error = saRecvRetry (ckptCheckpointInstance->fd, &res_lib_ckpt_sectionread, + sizeof (struct res_lib_ckpt_sectionread), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + dataLength = res_lib_ckpt_sectionread.header.size - sizeof (struct res_lib_ckpt_sectionread); + + /* + * Receive checkpoint section data + */ + if (dataLength > 0) { + error = saRecvRetry (ckptCheckpointInstance->fd, ioVector[i].dataBuffer, + dataLength, MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + } + if (res_lib_ckpt_sectionread.error != SA_OK) { + if (erroneousVectorIndex) { + *erroneousVectorIndex = i; + } + goto error_exit; + } + + /* + * Report back bytes of data read + */ + ioVector[i].readSize = res_lib_ckpt_sectionread.dataRead; + } + +error_exit: + pthread_mutex_unlock (&ckptCheckpointInstance->mutex); + return (error == SA_OK ? res_lib_ckpt_sectionread.error : error); +} + +SaErrorT +saCkptCheckpointSynchronize ( + const SaCkptCheckpointHandleT *checkpointHandle, + SaTimeT timeout) +{ + SaErrorT error; + struct ckptCheckpointInstance *ckptCheckpointInstance; + struct req_lib_ckpt_checkpointsynchronize req_lib_ckpt_checkpointsynchronize; + struct res_lib_ckpt_checkpointsynchronize res_lib_ckpt_checkpointsynchronize; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_checkpointsynchronize.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointsynchronize.header.size = sizeof (struct req_lib_ckpt_checkpointsynchronize); + req_lib_ckpt_checkpointsynchronize.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZE; + + error = saSendRetry (ckptCheckpointInstance->fd, &req_lib_ckpt_checkpointsynchronize, + sizeof (struct req_lib_ckpt_checkpointsynchronize), MSG_NOSIGNAL); + + if (error != SA_OK) { + goto error_exit; + } + + error = saRecvQueue (ckptCheckpointInstance->fd, &res_lib_ckpt_checkpointsynchronize, + 0, MESSAGE_RES_CKPT_CHECKPOINT_CHECKPOINTSYNCHRONIZE); + +error_exit: + return (error == SA_OK ? res_lib_ckpt_checkpointsynchronize.error : error); +} + +SaErrorT +saCkptCheckpointSynchronizeAsync ( + const SaCkptHandleT *ckptHandle, + SaInvocationT invocation, + const SaCkptCheckpointHandleT *checkpointHandle) +{ + struct ckptInstance *ckptInstance; + struct ckptCheckpointInstance *ckptCheckpointInstance; + SaErrorT error; + struct req_lib_ckpt_checkpointsynchronizeasync req_lib_ckpt_checkpointsynchronizeasync; + + error = saHandleConvert (&ckptCheckpointHandleDatabase, *checkpointHandle, + (void *)&ckptCheckpointInstance, CKPTCHECKPOINTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + error = saHandleConvert (&ckptHandleDatabase, *ckptHandle, + (void *)&ckptInstance, CKPTINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + goto error_exit; + } + + req_lib_ckpt_checkpointsynchronizeasync.header.magic = MESSAGE_MAGIC; + req_lib_ckpt_checkpointsynchronizeasync.header.size = sizeof (struct req_lib_ckpt_checkpointsynchronizeasync); + req_lib_ckpt_checkpointsynchronizeasync.header.id = MESSAGE_REQ_CKPT_CHECKPOINT_CHECKPOINTOPENASYNC; + req_lib_ckpt_checkpointsynchronizeasync.invocation = invocation; + + error = saSendRetry (ckptInstance->fd, &req_lib_ckpt_checkpointsynchronizeasync, + sizeof (struct req_lib_ckpt_checkpointsynchronizeasync), MSG_NOSIGNAL); + +error_exit: + return (error); +} diff --git a/lib/clm.c b/lib/clm.c index e69de29b..ebbad0c9 100644 --- a/lib/clm.c +++ b/lib/clm.c @@ -0,0 +1,476 @@ + +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_clm.h" +#include "../include/ais_msg.h" +#include "util.h" + +struct message_overlay { + struct message_header header; + char data[4096]; +}; + +struct clmInstance { + int fd; + SaClmCallbacksT callbacks; + struct message_overlay message; + pthread_mutex_t mutex; +}; +#define CLMINSTANCE_MUTEX_OFFSET offset_of(struct clmInstance, mutex) + +static struct saHandleDatabase clmHandleDatabase = { + handleCount: 0, + handles: 0, + generation: 0, + mutex: PTHREAD_MUTEX_INITIALIZER +}; + +/* + * Versions supported + */ +static SaVersionT clmVersionsSupported[] = { + { 'A', 1, 1 }, + { 'a', 1, 1 } +}; + +static struct saVersionDatabase clmVersionDatabase = { + sizeof (clmVersionsSupported) / sizeof (SaVersionT), + clmVersionsSupported +}; + + +SaErrorT +saClmInitialize ( + SaClmHandleT *clmHandle, + const SaClmCallbacksT *clmCallbacks, + const SaVersionT *version) +{ + struct clmInstance *clmInstance; + SaErrorT error = SA_OK; + + error = saVersionVerify (&clmVersionDatabase, version); + if (error != SA_OK) { + goto error_nofree; + } + + error = saHandleCreate (&clmHandleDatabase, (void *)&clmInstance, + sizeof (struct clmInstance), clmHandle); + if (error != SA_OK) { + goto error_nofree; + } + + error = saServiceConnect (&clmInstance->fd, MESSAGE_REQ_CLM_INIT); + if (error != SA_OK) { + goto error_free; + } + + memcpy (&clmInstance->callbacks, clmCallbacks, sizeof (SaClmCallbacksT)); + + pthread_mutex_init (&clmInstance->mutex, NULL); + + return (SA_OK); + +error_free: + saHandleRemove (&clmHandleDatabase, *clmHandle); +error_nofree: + return (error); +} + +SaErrorT +saClmSelectionObjectGet ( + const SaClmHandleT *clmHandle, + SaSelectionObjectT *selectionObject) +{ + struct clmInstance *clmInstance; + SaErrorT error; + + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + *selectionObject = clmInstance->fd; + + pthread_mutex_unlock (&clmInstance->mutex); + return (SA_OK); +} + +SaErrorT +saClmDispatch ( + const SaClmHandleT *clmHandle, + SaDispatchFlagsT dispatchFlags) +{ + struct pollfd ufds; + int timeout = -1; + SaErrorT error; + int cont = 1; /* always continue do loop except when set to 0 */ + int dispatch_avail; + int poll_fd; + int handle_verified = 0; + struct clmInstance *clmInstance; + struct res_clm_trackcallback *res_clm_trackcallback; + struct res_clm_nodegetcallback *res_clm_nodegetcallback; + SaClmCallbacksT callbacks; + unsigned int gen_first; + unsigned int gen_second; + + /* + * Timeout instantly for SA_DISPATCH_ONE or SA_DISPATCH_ALL and + * wait indefinately for SA_DISPATCH_BLOCKING + */ + if (dispatchFlags == SA_DISPATCH_ALL) { + timeout = 0; + } + + do { + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET, &gen_first); + if (error != SA_OK) { + return (handle_verified ? SA_OK : error); + } + handle_verified = 1; + + poll_fd = clmInstance->fd; + + /* + * Unlock mutex for potentially long wait in select. If fd + * is closed by clmFinalize in select, select will return + */ + + pthread_mutex_unlock (&clmInstance->mutex); + + ufds.fd = poll_fd; + ufds.events = POLLIN; + ufds.revents = 0; + + error = saPollRetry (&ufds, 1, timeout); + if (error != SA_OK) { + goto error_nounlock; + } + + dispatch_avail = ufds.revents & POLLIN; + if (dispatch_avail == 0 && dispatchFlags == SA_DISPATCH_ALL) { + break; /* exit do while cont is 1 loop */ + } + if (dispatch_avail == 0) { + continue; /* retry select */ + } + /* + * Re-verify amfHandle + */ + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET, &gen_second); + if (error != SA_OK) { + return (handle_verified ? SA_OK : error); + } + + /* + * Handle has been removed and then reallocated + */ + if (gen_first != gen_second) { + return SA_OK; + } + + /* + * Read header + */ + error = saRecvRetry (clmInstance->fd, &clmInstance->message.header, sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + + /* + * Read data payload + */ + if (clmInstance->message.header.size > sizeof (struct message_header)) { + error = saRecvRetry (clmInstance->fd, &clmInstance->message.data, + clmInstance->message.header.size - sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_unlock; + } + } + /* + * Make copy of callbacks, unlock instance, and call callback + * A risk of this dispatch method is that the callback routines may + * operate at the same time that amfFinalize has been called. + */ + memcpy (&callbacks, &clmInstance->callbacks, sizeof (SaClmCallbacksT)); + + pthread_mutex_unlock (&clmInstance->mutex); + + /* + * Dispatch incoming message + */ + switch (clmInstance->message.header.id) { + + case MESSAGE_RES_CLM_TRACKCALLBACK: + res_clm_trackcallback = (struct res_clm_trackcallback *)&clmInstance->message; + + memcpy (res_clm_trackcallback->notificationBufferAddress, + &res_clm_trackcallback->notificationBuffer, + res_clm_trackcallback->numberOfItems * sizeof (SaClmClusterNotificationT)); + + callbacks.saClmClusterTrackCallback ( + res_clm_trackcallback->notificationBufferAddress, + res_clm_trackcallback->numberOfItems, res_clm_trackcallback->numberOfMembers, + res_clm_trackcallback->viewNumber, SA_OK); + break; + + case MESSAGE_RES_CLM_NODEGETCALLBACK: + res_clm_nodegetcallback = (struct res_clm_nodegetcallback *)&clmInstance->message; + + memcpy (res_clm_nodegetcallback->clusterNodeAddress, + &res_clm_nodegetcallback->clusterNode, sizeof (SaClmClusterNodeT)); + + callbacks.saClmClusterNodeGetCallback ( + res_clm_nodegetcallback->invocation, + &res_clm_nodegetcallback->clusterNode, SA_OK); + break; + + default: + error = SA_ERR_LIBRARY; + goto error_nounlock; + break; + } + /* + * Determine if more messages should be processed + * */ + switch (dispatchFlags) { + case SA_DISPATCH_ONE: + cont = 0; + break; + case SA_DISPATCH_ALL: + break; + case SA_DISPATCH_BLOCKING: + break; + } + } while (cont); + + return (error); + +error_unlock: + pthread_mutex_unlock (&clmInstance->mutex); +error_nounlock: + return (error); +} + +SaErrorT +saClmFinalize ( + SaClmHandleT *clmHandle) +{ + struct clmInstance *clmInstance; + SaErrorT error; + + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET | HANDLECONVERT_DONTUNLOCKDB, 0); + if (error != SA_OK) { + return (error); + } + + shutdown (clmInstance->fd, 0); + close (clmInstance->fd); + free (clmInstance); + + error = saHandleRemove (&clmHandleDatabase, *clmHandle); + + pthread_mutex_unlock (&clmInstance->mutex); + + saHandleUnlockDatabase (&clmHandleDatabase); + + return (error); +} + +SaErrorT +saClmClusterTrackStart ( + const SaClmHandleT *clmHandle, + SaUint8T trackFlags, + SaClmClusterNotificationT *notificationBuffer, + SaUint32T numberOfItems) +{ + struct req_clm_trackstart req_trackstart; + struct clmInstance *clmInstance; + SaErrorT error = SA_OK; + + req_trackstart.header.magic = MESSAGE_MAGIC; + req_trackstart.header.size = sizeof (struct req_clm_trackstart); + req_trackstart.header.id = MESSAGE_REQ_CLM_TRACKSTART; + req_trackstart.trackFlags = trackFlags; + req_trackstart.notificationBufferAddress = notificationBuffer; + req_trackstart.numberOfItems = numberOfItems; + + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (clmInstance->fd, &req_trackstart, sizeof (struct req_clm_trackstart), MSG_NOSIGNAL); + + pthread_mutex_unlock (&clmInstance->mutex); + + return (error); +} + +SaErrorT +saClmClusterTrackStop ( + const SaClmHandleT *clmHandle) +{ + struct clmInstance *clmInstance; + struct req_clm_trackstop req_trackstop; + SaErrorT error = SA_OK; + + req_trackstop.header.magic = MESSAGE_MAGIC; + req_trackstop.header.size = sizeof (struct req_clm_trackstop); + req_trackstop.header.id = MESSAGE_REQ_CLM_TRACKSTOP; + + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (clmInstance->fd, &req_trackstop, sizeof (struct req_clm_trackstop), MSG_NOSIGNAL); + + pthread_mutex_unlock (&clmInstance->mutex); + + return (error); +} + +SaErrorT +saClmClusterNodeGet ( + SaClmNodeIdT nodeId, + SaTimeT timeout, + SaClmClusterNodeT *clusterNode) +{ + int fd; + struct req_clm_nodeget req_clm_nodeget; + struct res_clm_nodeget res_clm_nodeget; + struct message_overlay message; + SaErrorT error = SA_OK; + struct timeval select_timeout; + fd_set read_fds; + + select_timeout.tv_usec = 0; + select_timeout.tv_sec = 5; + + error = saServiceConnect (&fd, MESSAGE_REQ_CLM_INIT); + if (error != SA_OK) { + goto error_noclose; + } + + /* + * Send request message + */ + req_clm_nodeget.header.magic = MESSAGE_MAGIC; + req_clm_nodeget.header.size = sizeof (struct req_clm_nodeget); + req_clm_nodeget.header.id = MESSAGE_REQ_CLM_NODEGET; + req_clm_nodeget.nodeId = nodeId; + error = saSendRetry (fd, &req_clm_nodeget, sizeof (struct req_clm_nodeget), MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_close; + } + + FD_ZERO (&read_fds); + FD_SET (fd, &read_fds); + /* + * Wait for timeout interval + */ + error = saSelectRetry (fd + 1, &read_fds, 0, 0, &select_timeout); + if (error != SA_OK) { + goto error_close; + } + + /* + * Was there a timeout in receiving the information? + */ + if (FD_ISSET (fd, &read_fds) == 0) { + error = SA_ERR_TIMEOUT; + goto error_close; + } + + error = saRecvRetry (fd, &message.header, sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_close; + } + + error = saRecvRetry (fd, &message.data, message.header.size - sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_close; + } + + memcpy (clusterNode, &res_clm_nodeget.clusterNode, sizeof (SaClmClusterNodeT)); + +error_close: + close (fd); +error_noclose: + return (error); +} + +SaErrorT +saClmClusterNodeGetAsync ( + const SaClmHandleT *clmHandle, + SaInvocationT invocation, + SaClmNodeIdT nodeId, + SaClmClusterNodeT *clusterNode) +{ + struct clmInstance *clmInstance; + struct req_clm_nodeget req_clm_nodeget; + SaErrorT error = SA_OK; + + req_clm_nodeget.header.magic = MESSAGE_MAGIC; + req_clm_nodeget.header.size = sizeof (struct req_clm_nodeget); + req_clm_nodeget.header.id = MESSAGE_REQ_CLM_NODEGET; + memcpy (&req_clm_nodeget.invocation, &invocation, sizeof (SaInvocationT)); + memcpy (&req_clm_nodeget.nodeId, &nodeId, sizeof (SaClmNodeIdT)); + req_clm_nodeget.clusterNodeAddress = clusterNode; + + error = saHandleConvert (&clmHandleDatabase, *clmHandle, (void *)&clmInstance, CLMINSTANCE_MUTEX_OFFSET, 0); + if (error != SA_OK) { + return (error); + } + + error = saSendRetry (clmInstance->fd, &req_clm_nodeget, sizeof (struct req_clm_nodeget), MSG_NOSIGNAL); + + pthread_mutex_unlock (&clmInstance->mutex); + + return (error); +} diff --git a/lib/util.c b/lib/util.c index e69de29b..a9cadf02 100644 --- a/lib/util.c +++ b/lib/util.c @@ -0,0 +1,564 @@ + +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/ais_types.h" +#include "../include/ais_msg.h" +#include "util.h" + +SaErrorT +saServiceConnect ( + int *fdOut, + enum req_init_types initType) +{ + int fd; + int result; + struct sockaddr_un address; + struct req_lib_init req_lib_init; + struct res_lib_init res_lib_init; + SaErrorT error; + gid_t egid; + + /* + * Allow set group id binaries to be authenticated + */ + egid = getegid(); + setregid (egid, -1); + + memset (&address, 0, sizeof (struct sockaddr_un)); + address.sun_family = PF_UNIX; + strcpy (address.sun_path + 1, "libais.socket"); + fd = socket (PF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + return (SA_ERR_SYSTEM); + } + result = connect (fd, (struct sockaddr *)&address, sizeof (address)); + if (result == -1) { + return (SA_ERR_TRY_AGAIN); + } + + req_lib_init.header.magic = MESSAGE_MAGIC; + req_lib_init.header.size = sizeof (req_lib_init); + req_lib_init.header.id = initType; + + error = saSendRetry (fd, &req_lib_init, sizeof (struct req_lib_init), + MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + error = saRecvRetry (fd, &res_lib_init, + sizeof (struct res_lib_init), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + + /* + * Check for security errors + */ + if (res_lib_init.error != SA_OK) { + error = res_lib_init.error; + goto error_exit; + } + + *fdOut = fd; + return (SA_OK); +error_exit: + close (fd); + return (error); +} + +SaErrorT +saRecvRetry ( + int s, + void *msg, + size_t len, + int flags) +{ + SaErrorT error = SA_OK; + int result; + struct msghdr msg_recv; + struct iovec iov_recv; + + iov_recv.iov_base = (void *)msg; + iov_recv.iov_len = len; + + 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: + result = recvmsg (s, &msg_recv, flags); + if (result == -1 && errno == EINTR) { + goto retry_recv; + } + if (result == -1 || result != len) { + error = SA_ERR_SYSTEM; + } + return (error); +} + +struct message_overlay { + struct message_header header; + char instance[4096]; +}; + +SaErrorT +saRecvQueue ( + int s, + void *msg, + struct queue *queue, + int findMessageId) +{ + struct message_overlay *message_overlay = (struct message_overlay *)msg; + void *inq_msg; + int match; + SaErrorT error; + + do { + error = saRecvRetry (s, &message_overlay->header, sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + if (message_overlay->header.size > sizeof (struct message_header)) { + error = saRecvRetry (s, &message_overlay->instance, message_overlay->header.size - sizeof (struct message_header), MSG_WAITALL | MSG_NOSIGNAL); + if (error != SA_OK) { + goto error_exit; + } + } + match = (message_overlay->header.id == findMessageId); + + if (match == 0 && queue) { + inq_msg = (void *)malloc (message_overlay->header.size); + if (inq_msg == 0) { + error = SA_ERR_NO_MEMORY; + goto error_exit; + } + memcpy (inq_msg, msg, message_overlay->header.size); + error = saQueueItemAdd (queue, &inq_msg); + if (error != SA_OK) { + free (inq_msg); + goto error_exit; + } + + error = saActivatePoll (s); + if (error != SA_OK) { + goto error_exit; + } + } + } while (match == 0); + +error_exit: + return (error); +} + +SaErrorT +saActivatePoll (int s) { + struct req_amf_activatepoll req_amf_activatepoll; + SaErrorT error; + + /* + * Send activate poll to tell nodeexec to activate poll + * on this file descriptor + */ + req_amf_activatepoll.header.magic = MESSAGE_MAGIC; + req_amf_activatepoll.header.size = sizeof (req_amf_activatepoll); + req_amf_activatepoll.header.id = MESSAGE_REQ_AMF_ACTIVATEPOLL; + + error = saSendRetry (s, &req_amf_activatepoll, + sizeof (struct req_amf_activatepoll), MSG_NOSIGNAL); + return (error); +} + +SaErrorT +saSendRetry ( + int s, + const void *msg, + size_t len, + int flags) +{ + SaErrorT error = SA_OK; + int result; + + struct msghdr msg_send; + struct iovec iov_send; + + iov_send.iov_base = (void *)msg; + iov_send.iov_len = len; + + 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: + result = sendmsg (s, &msg_send, flags); + if (result == -1 && errno == EINTR) { + goto retry_send; + } + if (result == -1) { + error = SA_ERR_SYSTEM; + } + return (error); +} + +SaErrorT saSendMsgRetry ( + int s, + struct iovec *iov, + int iov_len) +{ + SaErrorT error = SA_OK; + int result; + + struct msghdr msg_send; + + msg_send.msg_iov = iov; + msg_send.msg_iovlen = iov_len; + 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: + result = sendmsg (s, &msg_send, MSG_NOSIGNAL); + if (result == -1 && errno == EINTR) { + goto retry_send; + } + if (result == -1) { + error = SA_ERR_SYSTEM; + } + return (error); +} + +SaErrorT +saSelectRetry ( + int s, + fd_set *readfds, + fd_set *writefds, + fd_set *exceptfds, + struct timeval *timeout) +{ + SaErrorT error = SA_OK; + int result; + +retry_select: + result = select (s, readfds, writefds, exceptfds, timeout); + if (result == -1 && errno == EINTR) { + goto retry_select; + } + if (result == -1) { + error = SA_ERR_SYSTEM; + } + + return (error); +} + +SaErrorT +saPollRetry ( + struct pollfd *ufds, + unsigned int nfds, + int timeout) +{ + SaErrorT error = SA_OK; + int result; + +retry_poll: + result = poll (ufds, nfds, timeout); + if (result == -1 && errno == EINTR) { + goto retry_poll; + } + if (result == -1) { + error = SA_ERR_SYSTEM; + } + + return (error); +} + +SaErrorT +saHandleVerify ( + struct saHandleDatabase *handleDatabase, + unsigned int handle) +{ + if (handle > handleDatabase->handleCount) { + return (SA_ERR_BAD_HANDLE); + } + if (handleDatabase->handles[handle].valid == 0) { + return (SA_ERR_BAD_HANDLE); + } + return (SA_OK); +} + +SaErrorT +saHandleCreate ( + struct saHandleDatabase *handleDatabase, + void **instanceOut, + int instanceSize, + int *handleOut) +{ + int handle; + void *newHandles; + int found = 0; + void *instance; + + pthread_mutex_lock (&handleDatabase->mutex); + + for (handle = 0; handle < handleDatabase->handleCount; handle++) { + if (handleDatabase->handles[handle].valid == 0) { + found = 1; + break; + } + } + if (found == 0) { + handleDatabase->handleCount += 1; + newHandles = (struct saHandle *)realloc (handleDatabase->handles, + sizeof (struct saHandle) * handleDatabase->handleCount); + if (newHandles == 0) { + pthread_mutex_unlock (&handleDatabase->mutex); + return (SA_ERR_NO_MEMORY); + } + handleDatabase->handles = newHandles; + } + instance = malloc (instanceSize); + if (instance == 0) { + return (SA_ERR_NO_MEMORY); + } + memset (instance, 0, instanceSize); + + handleDatabase->handles[handle].valid = 1; + handleDatabase->handles[handle].instance = instance; + handleDatabase->handles[handle].generation = handleDatabase->generation++; + + *handleOut = handle; + *instanceOut = instance; + + pthread_mutex_unlock (&handleDatabase->mutex); + return (SA_OK); +} + +SaErrorT +saHandleRemove ( + struct saHandleDatabase *handleDatabase, + unsigned int handle) +{ + free (handleDatabase->handles[handle].instance); + memset (&handleDatabase->handles[handle], 0, sizeof (struct saHandle)); + + return (SA_OK); +} + +SaErrorT +saHandleConvert ( + struct saHandleDatabase *handleDatabase, + unsigned int handle, + void **instance, + int offsetToMutex, + unsigned int *generationOut) +{ + SaErrorT error; + int unlockDatabase; + int locking; + + unlockDatabase = (0 == (offsetToMutex & HANDLECONVERT_DONTUNLOCKDB)); + locking = (0 == (offsetToMutex & HANDLECONVERT_NOLOCKING)); + offsetToMutex &= 0x00ffffff; /* remove 8 bits of flags */ + + if (locking) { + pthread_mutex_lock (&handleDatabase->mutex); + } + + error = saHandleVerify (handleDatabase, handle); + if (error != SA_OK) { + if (locking) { + pthread_mutex_unlock (&handleDatabase->mutex); + } + return (error); + } + + *instance = handleDatabase->handles[handle].instance; + if (generationOut) { + *generationOut = handleDatabase->handles[handle].generation; + } + + /* + * This function exits holding the mutex in the instance instance + * pointed to by offsetToMutex (if NOLOCKING isn't set) + */ + if (locking) { + pthread_mutex_lock ((pthread_mutex_t *)(*instance + offsetToMutex)); + if (unlockDatabase) { + pthread_mutex_unlock (&handleDatabase->mutex); + } + } + + return (SA_OK); +} + +SaErrorT +saHandleUnlockDatabase ( + struct saHandleDatabase *handleDatabase) +{ + pthread_mutex_unlock (&handleDatabase->mutex); + + return (SA_OK); +} + +SaErrorT +saVersionVerify ( + struct saVersionDatabase *versionDatabase, + const SaVersionT *version) +{ + int found = 0; + int i; + + if (version == 0) { + return (SA_ERR_VERSION); + } + + for (i = 0; i < versionDatabase->versionCount; i++) { + if (memcmp (&versionDatabase->versionsSupported[i], version, sizeof (SaVersionT)) == 0) { + found = 1; + break; + } + } + return (found ? SA_OK : SA_ERR_VERSION); +} + + +SaErrorT +saQueueInit ( + struct queue *queue, + int queueItems, + int bytesPerItem) +{ + queue->head = 0; + queue->tail = queueItems - 1; + queue->used = 0; + queue->usedhw = 0; + queue->size = queueItems; + queue->bytesPerItem = bytesPerItem; + queue->items = (void *)malloc (queueItems * bytesPerItem); + if (queue->items == 0) { + return (SA_ERR_NO_MEMORY); + } + memset (queue->items, 0, queueItems * bytesPerItem); + return (SA_OK); +} + +SaErrorT +saQueueIsFull ( + struct queue *queue, + int *isFull) +{ + *isFull = ((queue->size - 1) == queue->used); + return (SA_OK); +} + + +SaErrorT +saQueueIsEmpty ( + struct queue *queue, + int *isEmpty) +{ + *isEmpty = (queue->used == 0); + return (SA_OK); +} + + +SaErrorT +saQueueItemAdd ( + struct queue *queue, + void *item) +{ + char *queueItem; + int queuePosition; + + queuePosition = queue->head; + queueItem = queue->items; + queueItem += queuePosition * queue->bytesPerItem; + memcpy (queueItem, item, queue->bytesPerItem); + + if (queue->tail == queue->head) { + return (SA_ERR_LIBRARY); + } + queue->head = (queue->head + 1) % queue->size; + queue->used++; + if (queue->used > queue->usedhw) { + queue->usedhw = queue->used; + } + return (SA_OK); +} + +SaErrorT +saQueueItemGet (struct queue *queue, void **item) +{ + char *queueItem; + int queuePosition; + + queuePosition = (queue->tail + 1) % queue->size; + queueItem = queue->items; + queueItem += queuePosition * queue->bytesPerItem; + *item = (void *)queueItem; + return (SA_OK); +} + +SaErrorT +saQueueItemRemove (struct queue *queue) +{ + queue->tail = (queue->tail + 1) % queue->size; + if (queue->tail == queue->head) { + return (SA_ERR_LIBRARY); + } + queue->used--; + return (SA_OK); +} diff --git a/lib/util.h b/lib/util.h index e69de29b..c785e959 100644 --- a/lib/util.h +++ b/lib/util.h @@ -0,0 +1,186 @@ + +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include "../include/ais_msg.h" + +struct saHandle { + int valid; + void *instance; + unsigned int generation; +}; + +struct saHandleDatabase { + unsigned int handleCount; + struct saHandle *handles; + unsigned int generation; + pthread_mutex_t mutex; +}; + +struct saVersionDatabase { + int versionCount; + SaVersionT *versionsSupported; +}; + +struct queue { + int head; + int tail; + int used; + int usedhw; + int size; + void *items; + int bytesPerItem; +}; + +SaErrorT +saServiceConnect ( + int *fdOut, + enum req_init_types init_type); + +SaErrorT +saRecvRetry ( + int s, + void *msg, + size_t len, + int flags); + +SaErrorT +saRecvQueue ( + int s, + void *msg, + struct queue *queue, + int findMessageId); + +SaErrorT +saActivatePoll (int s); + +SaErrorT +saSendRetry ( + int s, + const void *msg, + size_t len, + int flags); + +SaErrorT saSendMsgRetry ( + int s, + struct iovec *iov, + int iov_len); + +SaErrorT +saSelectRetry ( + int s, + fd_set *readfds, + fd_set *writefds, + fd_set *exceptfds, + struct timeval *timeout); + +SaErrorT +saPollRetry ( + struct pollfd *ufds, + unsigned int nfds, + int timeout); + +SaErrorT +saHandleVerify ( + struct saHandleDatabase *handleDatabase, + unsigned int handle); + +SaErrorT +saHandleCreate ( + struct saHandleDatabase *handleDatabase, + void **instance, + int instanceSize, + int *handleOut); + +SaErrorT +saHandleRemove ( + struct saHandleDatabase *handleDatabase, + unsigned int handle); + +SaErrorT +saHandleConvert ( + struct saHandleDatabase *handleDatabase, + unsigned int handle, + void **instance, + int offsetToMutex, + unsigned int *generationOut); + + +SaErrorT +saHandleUnlockDatabase ( + struct saHandleDatabase *handleDatabase); + +SaErrorT +saVersionVerify ( + struct saVersionDatabase *versionDatabase, + const SaVersionT *version); + +SaErrorT +saQueueInit ( + struct queue *queue, + int queueItems, + int sizePerItem); + +SaErrorT +saQueueIsFull ( + struct queue *queue, + int *isFull); + +SaErrorT +saQueueIsEmpty ( + struct queue *queue, + int *isEmpty); + +SaErrorT +saQueueItemAdd ( + struct queue *queue, + void *item); + +SaErrorT +saQueueItemGet (struct queue *queue, void **item); + +SaErrorT +saQueueItemRemove (struct queue *queue); + +#define offset_of(type,member) (int)(&(((type *)0)->member)) + +#define HANDLECONVERT_NOLOCKING 0x80000000 +#define HANDLECONVERT_DONTUNLOCKDB 0x40000000 + +#endif /* AIS_UTIL_H_DEFINED */ diff --git a/loc b/loc index e69de29b..bf65a6e6 100644 --- a/loc +++ b/loc @@ -0,0 +1,14 @@ +wc -l exec/*.c exec/*.h include/*.h lib/*.c lib/*.h + +echo "Application Interface Specification Implementation Lines Of Code" +echo -n "exec LOC " +cat exec/*.c exec/*.h | wc -l + +echo -n "lib LOC " +cat lib/*.c lib/*.h | wc -l + +echo -n "include LOC " +cat include/*.h | wc -l + +echo -n "total LOC " +cat exec/*.c exec/*.h lib/*.c lib/*.h include/*.h | wc -l diff --git a/test/Makefile b/test/Makefile index e69de29b..4861ea79 100644 --- a/test/Makefile +++ b/test/Makefile @@ -0,0 +1,92 @@ +# 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. + +# Production mode flags +#CFLAGS = -c -O3 -Wall -I../include +#LDFLAGS = -L../lib +LIBS = ../lib/libais.a -lpthread + +# Debug mode flags +CFLAGS = -c -g -Wall -DDEBUG -I../include +LDFLAGS = -g -L../lib +LIBS = ../lib/libais.a -lpthread + +# Profile mode flags +#CFLAGS = -c -O3 -pg -DDEBUG -I../include +#LDFLAGS = -pg -L../lib +#LIBS = ../lib/libais.a + +EXTRA_CFLAGS = -I../include +all: testclm testamf testamf1 testamf2 testamf3 testamf4 testamf5 testamf6 testamfth testckpt ckptstress testparse + +testparse: testparse.o + $(CC) $(LDFLAGS) -o testparse testparse.o ../exec/parse.o ../exec/print.o ../exec/mempool.o + +testtimer: testtimer.o + $(CC) $(LDFLAGS) -o testtimer testtimer.o ../exec/timer.o + +testamf: testamf.o + $(CC) $(LDFLAGS) -o testamf testamf.o $(LIBS) + +testamf1: testamf1.o + $(CC) $(LDFLAGS) -o testamf1 testamf1.o $(LIBS) + +testamf2: testamf2.o + $(CC) $(LDFLAGS) -o testamf2 testamf2.o $(LIBS) + +testamf3: testamf3.o + $(CC) $(LDFLAGS) -o testamf3 testamf3.o $(LIBS) + +testamf4: testamf4.o + $(CC) $(LDFLAGS) -o testamf4 testamf4.o $(LIBS) + +testamf5: testamf5.o + $(CC) $(LDFLAGS) -o testamf5 testamf5.o $(LIBS) + +testamf6: testamf6.o + $(CC) $(LDFLAGS) -o testamf6 testamf6.o $(LIBS) + +testamfth: testamfth.o + $(CC) $(LDFLAGS) -o testamfth testamfth.o $(LIBS) + +testclm: testclm.o + $(CC) $(LDFLAGS) -o testclm testclm.o $(LIBS) + +testckpt: testckpt.o + $(CC) $(LDFLAGS) -o testckpt testckpt.o $(LIBS) + +ckptstress: ckptstress.o + $(CC) $(LDFLAGS) -o ckptstress ckptstress.o $(LIBS) + +clean: + rm -f *.o testclm testamf testamf1 testamf2 testamf3 testamf4 testamf5 testamf6 testamfth testckpt ckptstress testparse testtimer + +%.o: %.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< diff --git a/test/ckptstress.c b/test/ckptstress.c index e69de29b..8b42112d 100644 --- a/test/ckptstress.c +++ b/test/ckptstress.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_ckpt.h" + +int ckptinv; +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +SaVersionT version = { 'A', 1, 1 }; + +SaNameT checkpointName = { 5, "abra\0" }; + +SaCkptCheckpointCreationAttributesT checkpointCreationAttributes = { + SA_CKPT_WR_ALL_REPLICAS, + 100000, + 0, + 5, + 20000, + 10 +}; + +SaCkptSectionIdT sectionId1 = { + "section ID #1", + 14 +}; + +SaCkptSectionIdT sectionId2 = { + "section ID #2", + 14 +}; +SaCkptSectionCreationAttributesT sectionCreationAttributes1 = { + §ionId1, + 0xFFFFFFFF +}; + +SaCkptSectionCreationAttributesT sectionCreationAttributes2 = { + §ionId2, + 0xFFFFFFFF +}; + +char readBuffer1[1025]; + +char readBuffer2[1025]; + +SaCkptIOVectorElementT ReadVectorElements[] = { + { + { + "section ID #1", + 14 + }, + readBuffer1, + sizeof (readBuffer1), + 0, + 0 + }, + { + { + "section ID #2", + 14 + }, + readBuffer2, + sizeof (readBuffer2), + 0, + 0 + } +}; + +#define DATASIZE 250000 +char data[DATASIZE]; +SaCkptIOVectorElementT WriteVectorElements[] = { + { + { + "section ID #1", + 14 + }, + data, /*"written data #1, this should extend past end of old section data", */ + DATASIZE, /*sizeof ("written data #1, this should extend past end of old section data") + 1, */ + 0, //5, + 0 + } +#ifdef COMPILE_OUT + { + { + "section ID #2", + 14 + }, + data, /*"written data #2, this should extend past end of old section data" */ + DATASIZE, /*sizeof ("written data #2, this should extend past end of old section data") + 1, */ + 0, //3, + 0 + } +#endif +}; + +void *th_dispatch (void *arg) +{ + int th = (int)arg; + SaCkptCheckpointHandleT handle; + SaErrorT error; + int i; + SaUint32T erroroneousVectorIndex = 0; + + error = saCkptCheckpointOpen (&checkpointName, + &checkpointCreationAttributes, + SA_CKPT_CHECKPOINT_READ|SA_CKPT_CHECKPOINT_WRITE, + 0, + &handle); + for (i = 0; i < 1000; i++) { + error = saCkptCheckpointWrite (&handle, + WriteVectorElements, + 1,/* placing two here with only one vector element causes an assertion failure !! */ + &erroroneousVectorIndex); + printf ("Thread %d: Attempt %d: error %d\n", th, i, error); + if (error != SA_OK) { + printf ("Thread %d: Error from write.\n", th); + } + } + return (0); +} + +int main (void) { + SaCkptCheckpointHandleT checkpointHandle; + SaErrorT error; + int i; + pthread_t dispatch_thread; + + error = saCkptCheckpointOpen (&checkpointName, + &checkpointCreationAttributes, + SA_CKPT_CHECKPOINT_READ|SA_CKPT_CHECKPOINT_WRITE, + 0, + &checkpointHandle); + printf ("first open result %d (should be 1)\n", error); + + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes1, + "Initial Data #0", + strlen ("Initial Data #0") + 1); +printf ("create2 error is %d\n", error); + + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes2, + "Initial Data #0", + strlen ("Initial Data #0") + 1); +printf ("create2 error is %d\n", error); + + for (i = 0; i < 40; i++) { + pthread_create (&dispatch_thread, NULL, th_dispatch, (void *)i); + } + pthread_join (dispatch_thread, NULL); + return (0); +} diff --git a/test/scripts/spam b/test/scripts/spam index e69de29b..677c416d 100644 --- a/test/scripts/spam +++ b/test/scripts/spam @@ -0,0 +1,999 @@ +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & +./testclm & +./testamf & diff --git a/test/scripts/spam2 b/test/scripts/spam2 index e69de29b..f819c46a 100644 --- a/test/scripts/spam2 +++ b/test/scripts/spam2 @@ -0,0 +1,82 @@ +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & +./testamf & diff --git a/test/testamf.c b/test/testamf.c index e69de29b..a8ec0f4c 100644 --- a/test/testamf.c +++ b/test/testamf.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" +#include "ais_msg.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to stop, stopping.\n"); + saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback invocation id %x compName ", invocation); + printSaNameT ((SaNameT *)compName); + printf (" csiName "); + printSaNameT ((SaNameT *)csiName); + printf ("\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaAmfHandleT handle; + SaAmfHandleT handleproxy; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + SaNameT proxyCompName; + SaNameT csiName; + SaAmfReadinessStateT readinessState; + SaAmfComponentCapabilityModelT componentCapabilityModel; + SaAmfProtectionGroupNotificationT protectionGroupNotificationBuffer[64]; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + result = saAmfInitialize (&handleproxy, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + saAmfSelectionObjectGet (&handleproxy, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "raidupdate1"); + setSanameT (&proxyCompName, "raidhotswap1"); + setSanameT (&csiName, "raidupdate"); + + + result = saAmfComponentRegister (&handleproxy, &proxyCompName, NULL); + printf ("register result is %d (should be 1)\n", result); + result = saAmfComponentRegister (&handle, &compName, &proxyCompName); + printf ("register result is %d (should be 1)\n", result); + result = saAmfComponentCapabilityModelGet (&compName, &componentCapabilityModel); + printf ("component capability model get is %d (should be 1)\n", result); + result = saAmfProtectionGroupTrackStart (&handle, &csiName, SA_TRACK_CURRENT | SA_TRACK_CHANGES_ONLY, protectionGroupNotificationBuffer, 64); + printf ("track start result is %d (should be 1)\n", result); +#ifdef COMPILEOUT + result = saAmfProtectionGroupTrackStop (&handle, &csiName); + printf ("track stop result is %d (should be 1)\n", result); + result = saAmfComponentUnregister (&handle, &compName, &compName); + printf ("unregister result is %d (should be 21)\n", result); + result = saAmfComponentRegister (&handle, &compName, &proxyCompName); + printf ("register result is %d (should be 14)\n", result); + result = saAmfComponentUnregister (&handle, &compName, &proxyCompName); + printf ("unregister result is %d (should be 1)\n", result); + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + result = saAmfComponentUnregister (&handle, &compName, NULL); + printf ("unregister result is %d (should be 1)\n", result); + result = saAmfCompNameGet (&handle, &newCompName); + printf ("compNameGet result is %d (should be 12)\n", result); + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + result = saAmfCompNameGet (&handle, &newCompName); + printf ("compNameGet result is %d (should be 1)\n", result); + result = saAmfReadinessStateGet (&compName, &readinessState); + printf ("readinessStateGet result is %d (should be 1) state %d (should be 1)\n", result, readinessState); + proxyCompName.value[0] = 'a'; +#endif + result = saAmfReadinessStateGet (&proxyCompName, &readinessState); + printf ("readinessStateGet result is %d (should be 12)\n", result); + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); +// printf ("dispatching handleproxy\n"); + saAmfDispatch (&handleproxy, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + + return (0); +} diff --git a/test/testamf1.c b/test/testamf1.c index e69de29b..bb821156 100644 --- a/test/testamf1.c +++ b/test/testamf1.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); + saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +static struct sched_param sched_param = { + sched_priority: 99 +}; + +int main (void) { + SaAmfHandleT handle; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + + result = sched_setscheduler (0, SCHED_RR, &sched_param); + if (result == -1) { +printf ("couldn't set sched priority\n"); + } + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "comp_a_in_su_x"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + + exit (0); +} diff --git a/test/testamf2.c b/test/testamf2.c index e69de29b..8d57a8b5 100644 --- a/test/testamf2.c +++ b/test/testamf2.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + printf ("Healthcheck Count is %d\n", healthcheck_count++); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaAmfHandleT handle; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + int i; + SaAmfErrorDescriptorT errorDescriptor; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "comp_b_in_su_x"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + + printf ("register result is %d (should be 1)\n", result); + + i = 0; + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); +// } while (1); + } while (i++ < 4); + + printf ("Unregistering component\n"); + result = saAmfComponentUnregister (&handle, &compName, NULL); + +// select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + + sleep (1); + printf ("Registering component\n"); + result = saAmfComponentRegister (&handle, &compName, NULL); + + sleep (1); + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + + printf ("REPORTING ERROR.\n"); + errorDescriptor.probableCause = 5; + result = saAmfErrorReport (&compName, &compName, + 0, + &errorDescriptor, + NULL); + + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + + sleep (1); + printf ("CANCELING ERROR.\n"); + result = saAmfErrorCancelAll (&compName); + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + + return (0); +} diff --git a/test/testamf3.c b/test/testamf3.c index e69de29b..e5523c85 100644 --- a/test/testamf3.c +++ b/test/testamf3.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); + saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaAmfHandleT handle; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "comp_a_in_su_y"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + + exit (0); +} diff --git a/test/testamf4.c b/test/testamf4.c index e69de29b..8e7669f1 100644 --- a/test/testamf4.c +++ b/test/testamf4.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaAmfHandleT handle; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "comp_b_in_su_y"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + + exit (0); +} diff --git a/test/testamf5.c b/test/testamf5.c index e69de29b..fe9a2471 100644 --- a/test/testamf5.c +++ b/test/testamf5.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); + saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaAmfHandleT handle; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "comp_a_in_su_z"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + + return (0); +} diff --git a/test/testamf6.c b/test/testamf6.c index e69de29b..706ed135 100644 --- a/test/testamf6.c +++ b/test/testamf6.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + SaErrorT res; + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + res = saAmfResponse (invocation, SA_OK); + printf ("response res is %d\n", res); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaAmfHandleT handle; + int result; + int select_fd; + fd_set read_fds; + SaNameT compName; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + FD_ZERO (&read_fds); + saAmfSelectionObjectGet (&handle, &select_fd); + FD_SET (select_fd, &read_fds); + + setSanameT (&compName, "comp_b_in_su_z"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + + do { + select (select_fd + 1, &read_fds, 0, 0, 0); + saAmfDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saAmfFinalize (&handle); + return (0); +} diff --git a/test/testamfth.c b/test/testamfth.c index e69de29b..2151e3cc 100644 --- a/test/testamfth.c +++ b/test/testamfth.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_amf.h" +#include "ais_msg.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void setSanameT (SaNameT *name, char *str) { + name->length = strlen (str); + memcpy (name->value, str, name->length); +} + +int healthcheck_count = 0; +void HealthcheckCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfHealthcheckT checkType) +{ + +// if (healthcheck_count++ % 20 == 19) { + printf ("20 HealthcheckCallback have occured for component: "); + printSaNameT ((SaNameT *)compName); + printf ("\n"); +// } + saAmfResponse (invocation, SA_OK); + +} + +void ReadinessStateSetCallback (SaInvocationT invocation, + const SaNameT *compName, + SaAmfReadinessStateT readinessState) +{ + switch (readinessState) { + case SA_AMF_IN_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_IN_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_OUT_OF_SERVICE: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_OUT_OF_SERVICE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STOPPING: + printf ("ReadinessStateSetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' requested to enter operational state SA_AMF_STOPPING.\n"); + saAmfStoppingComplete (invocation, SA_OK); + break; + } +} + +void ComponentTerminateCallback ( + SaInvocationT invocation, + const SaNameT *compName) +{ + printf ("ComponentTerminateCallback\n"); +} + +void CSISetCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + SaAmfCSIFlagsT csiFlags, + SaAmfHAStateT *haState, + SaNameT *activeCompName, + SaAmfCSITransitionDescriptorT transitionDescriptor) +{ + switch (*haState) { + case SA_AMF_ACTIVE: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_ACTIVE.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_STANDBY: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_STANDBY.\n"); + saAmfResponse (invocation, SA_OK); + break; + case SA_AMF_QUIESCED: + printf ("CSISetCallback: '"); + printSaNameT ((SaNameT *)compName); + printf ("' for CSI '"); + printSaNameT ((SaNameT *)compName); + printf ("'"); + printf (" requested to enter hastate SA_AMF_QUIESCED.\n"); + saAmfResponse (invocation, SA_OK); + break; + } +} + +void CSIRemoveCallback ( + SaInvocationT invocation, + const SaNameT *compName, + const SaNameT *csiName, + const SaAmfCSIFlagsT *csiFlags) +{ + printf ("CSIRemoveCallback for component '"); + printSaNameT ((SaNameT *)compName); + printf ("' in CSI '"); + printSaNameT ((SaNameT *)csiName); + printf ("'\n"); + saAmfResponse (invocation, SA_OK); +} + +void ProtectionGroupTrackCallback ( + const SaNameT *csiName, + SaAmfProtectionGroupNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaErrorT error) +{ + int i; + + printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems, (int)numberOfMembers); + printf ("buffer is %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + printf ("component name"); + printSaNameT (¬ificationBuffer[i].member.compName); + printf ("\n"); + printf ("\treadiness state is %d\n", notificationBuffer[i].member.readinessState); + printf ("\thastate %d\n", notificationBuffer[i].member.haState); + printf ("\tchange is %d\n", notificationBuffer[i].change); + + } +} + +void ExternalComponentRestartCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName) +{ + printf ("ExternalComponentRestartCallback\n"); +} + +void ExternalComponentControlCallback ( + const SaInvocationT invocation, + const SaNameT *externalCompName, + SaAmfExternalComponentActionT controlAction) +{ + printf ("ExternalComponentControlCallback\n"); +} + +void PendingOperationConfirmCallback ( + const SaInvocationT invocation, + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationConfirmCallback\n"); +} + +void PendingOperationExpiredCallback ( + const SaNameT *compName, + SaAmfPendingOperationFlagsT pendingOperationFlags) +{ + printf ("PendingOperationExpiredCallback\n"); +} + +SaAmfCallbacksT amfCallbacks = { + HealthcheckCallback, + ReadinessStateSetCallback, + ComponentTerminateCallback, + CSISetCallback, + CSIRemoveCallback, + ProtectionGroupTrackCallback, + ExternalComponentRestartCallback, + ExternalComponentControlCallback, + PendingOperationConfirmCallback, + PendingOperationExpiredCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +void *th_dispatch (void *arg) +{ + SaErrorT result; + SaAmfHandleT *handle = (SaAmfHandleT *)arg; + + printf ("THREAD DISPATCH starting.\n"); + result = saAmfDispatch (handle, SA_DISPATCH_BLOCKING); + printf ("THREAD DISPATCH return result is %d\n", result); + return (0); +} + +int main (void) { + SaAmfHandleT handle; + int result; + SaNameT compName; + pthread_t dispatch_thread; + + result = saAmfInitialize (&handle, &amfCallbacks, &version); + if (result != SA_OK) { + printf ("initialize result is %d\n", result); + exit (1); + } + + setSanameT (&compName, "raidupdate1"); + + result = saAmfComponentRegister (&handle, &compName, NULL); + printf ("register result is %d (should be 1)\n", result); + + pthread_create (&dispatch_thread, NULL, th_dispatch, &handle); + + sleep (5); + +printf ("Finalizing handle\n"); + saAmfFinalize (&handle); + sleep (1); /* this sleep isn't really necessary */ + result = saAmfInitialize (&handle, &amfCallbacks, &version); + result = saAmfComponentRegister (&handle, &compName, NULL); + pthread_create (&dispatch_thread, NULL, th_dispatch, &handle); + sleep (10); + + exit (0); +} diff --git a/test/testckpt.c b/test/testckpt.c index e69de29b..ff5a89b4 100644 --- a/test/testckpt.c +++ b/test/testckpt.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_ckpt.h" + +int ckptinv; +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +SaVersionT version = { 'A', 1, 1 }; + +SaNameT checkpointName = { 5, "abra\0" }; + +SaCkptCheckpointCreationAttributesT checkpointCreationAttributes = { + SA_CKPT_WR_ALL_REPLICAS, + 100000, + 0, + 5, + 20000, + 10 +}; + +SaCkptSectionIdT sectionId1 = { + "section ID #1", + 14 +}; + +SaCkptSectionIdT sectionId2 = { + "section ID #2", + 14 +}; +SaCkptSectionCreationAttributesT sectionCreationAttributes1 = { + §ionId1, + 0xFFFFFFFF +}; + +SaCkptSectionCreationAttributesT sectionCreationAttributes2 = { + §ionId2, + 0xFFFFFFFF +}; + +char readBuffer1[1025]; + +char readBuffer2[1025]; + +SaCkptIOVectorElementT ReadVectorElements[] = { + { + { + "section ID #1", + 14 + }, + readBuffer1, + sizeof (readBuffer1), + 0, + 0 + }, + { + { + "section ID #2", + 14 + }, + readBuffer2, + sizeof (readBuffer2), + 0, + 0 + } +}; + +#define DATASIZE 127000 +char data[DATASIZE]; +SaCkptIOVectorElementT WriteVectorElements[] = { + { + { + "section ID #1", + 14 + }, + data, /*"written data #1, this should extend past end of old section data", */ + DATASIZE, /*sizeof ("data #1, this should extend past end of old section data") + 1, */ + 0, //5, + 0 + } +#ifdef COMPILE_OUT + { + { + "section ID #2", + 14 + }, + data, /*"written data #2, this should extend past end of old section data" */ + DATASIZE, /*sizeof ("written data #2, this should extend past end of old section data") + 1, */ + 0, //3, + 0 + } +#endif +}; + +int main (void) { + SaCkptCheckpointHandleT checkpointHandle; + SaCkptCheckpointHandleT checkpointHandle2; + SaCkptCheckpointHandleT checkpointHandleRead; + SaCkptCheckpointStatusT checkpointStatus; + SaCkptSectionIteratorT sectionIterator; + SaCkptSectionDescriptorT sectionDescriptor; + SaUint32T erroroneousVectorIndex = 0; + SaErrorT error; + + error = saCkptCheckpointOpen (&checkpointName, + &checkpointCreationAttributes, + SA_CKPT_CHECKPOINT_READ|SA_CKPT_CHECKPOINT_WRITE, + 0, + &checkpointHandle); + printf ("first open result %d (should be 1)\n", error); + +// start of stuff + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes1, + "Initial Data #0", + strlen ("Initial Data #0") + 1); +printf ("create1 error is %d\n", error); + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes2, + "Initial Data #0", + strlen ("Initial Data #0") + 1); +printf ("create2 error is %d\n", error); + printf ("saCkptSectionCreate result %d (should be 1)\n", error); +for (ckptinv = 0; ckptinv < 500000; ckptinv++) { +printf ("Writing checkpoint loop %d\n", ckptinv); + /* + * Test checkpoint write + */ + error = saCkptCheckpointWrite (&checkpointHandle, + WriteVectorElements, + 1, + &erroroneousVectorIndex); +if (error != SA_OK) { + printf ("saCkptCheckpointWrite result %d (should be 1)\n", error); + exit (1); +} +} +exit (1); + + error = saCkptCheckpointUnlink (&checkpointName); + printf ("unlink result %d (should be 1)\n", error); + + error = saCkptCheckpointOpen (&checkpointName, + &checkpointCreationAttributes, + SA_CKPT_CHECKPOINT_READ|SA_CKPT_CHECKPOINT_WRITE, + 0, + &checkpointHandle2); + printf ("open after unlink result %d (should be 7)\n", error); + + error = saCkptCheckpointClose (&checkpointHandle); + printf ("close result %d (should be 1)\n", error); + + error = saCkptCheckpointOpen (&checkpointName, + &checkpointCreationAttributes, + SA_CKPT_CHECKPOINT_READ, + 0, + &checkpointHandleRead); + printf ("read only open result %d (should be 1)\n", error); + + error = saCkptCheckpointOpen (&checkpointName, + &checkpointCreationAttributes, + SA_CKPT_CHECKPOINT_READ|SA_CKPT_CHECKPOINT_WRITE, + 0, + &checkpointHandle); + printf ("open after unlink/close result %d (should be 1)\n", error); + + error = saCkptCheckpointRetentionDurationSet (&checkpointHandle, + 10000); + printf ("set checkpoint retention duration result %d (should be 1)\n", error); + + error = saCkptCheckpointStatusGet (&checkpointHandle, + &checkpointStatus); + printf ("saCkptCheckpointStatusGet result %d (should be 1)\n", error); + if (error == SA_OK) { + printf ("Memory used %d in %d sections.\n", (int)checkpointStatus.memoryUsed, + (int)checkpointStatus.numberOfSections); + } + + error = saCkptSectionCreate (&checkpointHandleRead, + §ionCreationAttributes1, + "Initial Data #0", + strlen ("Initial Data #0") + 1); + printf ("saCkptSectionCreate result %d (should be 11)\n", error); + + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes1, + "Initial Data #0", + strlen ("Initial Data #0") + 1); + printf ("saCkptSectionCreate result %d (should be 1)\n", error); + + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes1, + "Initial Data #0", + strlen ("Initial Data #0") + 1); + printf ("saCkptSectionCreate result %d (should be 14)\n", error); + +#ifdef COMPILE_OUT + error = saCkptSectionDelete (&checkpointHandle, + §ionId1); + printf ("saCkptSectionDelete result %d (should be 1)\n", error); + + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes1, + "Initial Data #0", + strlen ("Initial Data #0") + 1); + printf ("saCkptSectionCreate result %d (should be 1)\n", error); +#endif + + error = saCkptSectionExpirationTimeSet (&checkpointHandle, + §ionId1, + 0xFFAAAAAA); + printf ("saCkptSectionExpirationTimeSet result %d (should be 1)\n", error); + + + error = saCkptSectionOverwrite (&checkpointHandle, + §ionId1, + "Overwrite Data #1", + strlen ("Overwrite Data #1") + 1); + printf ("saCkptSectionOverwrite result %d (should be 1)\n", error); + + /* + * Test checkpoint read + */ + memset (readBuffer1, 0, sizeof (readBuffer1)); + memset (readBuffer2, 0, sizeof (readBuffer2)); + error = saCkptSectionCreate (&checkpointHandle, + §ionCreationAttributes2, + "Initial Data #2", + strlen ("Initial Data #2") + 1); + printf ("saCkptSectionCreate result %d (should be 1)\n", error); + + error = saCkptCheckpointRead (&checkpointHandle, + ReadVectorElements, + 2, + &erroroneousVectorIndex); + printf ("saCkptCheckpointRead result %d (should be 1)\n", error); + printf ("Buffers after checkpoint read\n"); + printf (" buffer #1: '%s'\n", readBuffer1); + printf (" buffer #2: '%s'\n", readBuffer2); + +//sleep (20); +for (ckptinv = 0; ckptinv < 2000; ckptinv++) { + /* + * Test checkpoint write + */ + error = saCkptCheckpointWrite (&checkpointHandle, + WriteVectorElements, + 2, + &erroroneousVectorIndex); +if (error != SA_OK) { +printf ("Writing checkpoint loop %d\n", ckptinv); + printf ("saCkptCheckpointWrite result %d (should be 1)\n", error); +exit (1); +} +} +exit (1); + error = saCkptCheckpointRead (&checkpointHandle, + ReadVectorElements, + 2, + &erroroneousVectorIndex); +// printf ("saCkptCheckpointRead result %d (should be 1)\n", error); +// printf ("Buffers after checkpoint write are:\n"); +// printf (" buffer #1: '%s'\n", readBuffer1); +// printf (" buffer #2: '%s'\n", readBuffer2); + + error = saCkptCheckpointStatusGet (&checkpointHandle, + &checkpointStatus); + printf ("saCkptCheckpointStatusGet result %d (should be 1)\n", error); + if (error == SA_OK) { + printf ("Memory used %d in %d sections.\n", (int)checkpointStatus.memoryUsed, + (int)checkpointStatus.numberOfSections); + } + error = saCkptSectionIteratorInitialize (&checkpointHandle, + 0, + 0, + §ionIterator); + printf ("saCkptSectionIteratorInitialize result %d (should be 1)\n", error); + + /* + * Iterate all sections + */ + do { + error = saCkptSectionIteratorNext (§ionIterator, + §ionDescriptor); + printf ("saCkptSectionIteratorNext result %d (should be 1)\n", error); + if (error == SA_OK) { + printf ("Section '%s' expires %llx size %d state %x update %llx\n", + sectionDescriptor.sectionId.id, + sectionDescriptor.expirationTime, + sectionDescriptor.sectionSize, + sectionDescriptor.sectionState, + sectionDescriptor.lastUpdate); + } + } while (error == SA_OK); + + error = saCkptSectionIteratorFinalize (§ionIterator); + printf ("saCkptSectionIteratorFinalize result %d (should be 1)\n", error); + return (0); +} diff --git a/test/testclm.c b/test/testclm.c index e69de29b..e58d8c09 100644 --- a/test/testclm.c +++ b/test/testclm.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2002-2003 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include +#include +#include +#include + +#include "ais_types.h" +#include "ais_clm.h" + +void printSaClmNodeAddressT (SaClmNodeAddressT *nodeAddress) { + int i; + + for (i = 0; i < nodeAddress->length; i++) { + printf ("%d.", nodeAddress->value[i]); + } +} + +void printSaNameT (SaNameT *name) +{ + int i; + + for (i = 0; i < name->length; i++) { + printf ("%c", name->value[i]); + } +} + +void printSaClmClusterNodeT (char *description, SaClmClusterNodeT *clusterNode) { + printf ("Node Information for %s\n", description); + + printf ("\tnode id is %x\n", (int)clusterNode->nodeId); + + printf ("\tnode address is "); + printSaClmNodeAddressT (&clusterNode->nodeAddress); + printf ("\n"); + + printf ("\tNode name is "); + printSaNameT (&clusterNode->nodeName); + printf ("\n"); + + printf ("\tCluster name is "); + printSaNameT (&clusterNode->clusterName); + printf ("\n"); + + printf ("\tMember is %d\n", clusterNode->member); + + printf ("\tTimestamp is %llx nanoseconds\n", clusterNode->bootTimestamp); +} + +void NodeGetCallback ( + SaInvocationT invocation, + SaClmClusterNodeT *clusterNode, + SaErrorT error) +{ + char buf[128]; + + if (invocation == 0x60) { + sprintf (buf, "NodeGetCallback different machine invocation %x", invocation); + } else { + sprintf (buf, "NodeGetCallback local machine %x", invocation); + } + + + printSaClmClusterNodeT (buf, clusterNode); +} + +void TrackCallback ( + SaClmClusterNotificationT *notificationBuffer, + SaUint32T numberOfItems, + SaUint32T numberOfMembers, + SaUint64T viewNumber, + SaErrorT error) +{ + int i; + + printf ("Calling track callback %p\n", notificationBuffer); + for (i = 0; i < numberOfItems; i++) { + switch (notificationBuffer[i].clusterChanges) { + case SA_CLM_NODE_NO_CHANGE: + printf ("NODE STATE NO CHANGE.\n"); + break; + case SA_CLM_NODE_JOINED: + printf ("NODE STATE JOINED.\n"); + break; + case SA_CLM_NODE_LEFT: + printf ("NODE STATE LEFT.\n"); + break; + } + printSaClmClusterNodeT ("TRACKING", ¬ificationBuffer[i].clusterNode); + } + printf ("Done calling trackCallback\n"); +} + +SaClmCallbacksT callbacks = { + NodeGetCallback, + TrackCallback +}; + +SaVersionT version = { 'A', 1, 1 }; + +int main (void) { + SaClmHandleT handle; + fd_set read_fds; + int select_fd; + int result; + SaClmClusterNotificationT clusterNotificationBuffer[64]; + + result = saClmInitialize (&handle, &callbacks, &version); + if (result != SA_OK) { + printf ("Could not initialize Cluster Membership API instance error %d\n", result); + exit (1); + } + +// result = saClmClusterNodeGet (0x6201a8c0, 0, &clusterNode); +// printSaClmClusterNodeT ("saClmClusterNodeGet ip 192.168.1.98", &clusterNode); +#ifdef COMPILE_OUT + result = saClmClusterNodeGet (SA_CLM_LOCAL_NODE_ID, 0, &clusterNode); + + printSaClmClusterNodeT ("saClmClusterNodeGet SA_CLM_LOCAL_NODE_ID", &clusterNode); + + result = saClmClusterNodeGetAsync (&handle, 0x55, SA_CLM_LOCAL_NODE_ID, &clusterNode); + printf ("result is %d\n", result); + + result = saClmClusterNodeGetAsync (&handle, 0x60, 0x6201a8c0, &clusterNode); + printf ("result is %d\n", result); + result = saClmClusterNodeGetAsync (&handle, 0x59, SA_CLM_LOCAL_NODE_ID, &clusterNode); + printf ("result is %d\n", result); + + result = saClmClusterNodeGetAsync (&handle, 0x57, SA_CLM_LOCAL_NODE_ID, &clusterNode); + printf ("result is %d\n", result); + +#endif + +printf ("notify buffer is %p\n", clusterNotificationBuffer); + saClmClusterTrackStart (&handle, SA_TRACK_CURRENT | SA_TRACK_CHANGES_ONLY, clusterNotificationBuffer, 64); + + saClmSelectionObjectGet (&handle, &select_fd); + +printf ("select fd is %d\n", select_fd); + FD_ZERO (&read_fds); + FD_SET (select_fd, &read_fds); + do { +printf ("starting select\n"); + result = select (select_fd + 1, &read_fds, 0, 0, 0); + if (result == -1) { + perror ("select\n"); + } +printf ("done with select\n"); + saClmDispatch (&handle, SA_DISPATCH_ALL); + } while (result); + + saClmClusterTrackStop (&handle); + saClmFinalize (&handle); + + return (0); +} diff --git a/test/testparse.c b/test/testparse.c index e69de29b..ce2dd7c1 100644 --- a/test/testparse.c +++ b/test/testparse.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2002-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include "../include/ais_types.h" +#include "../exec/parse.h" +#include "../exec/print.h" + +int main (void) +{ + char *error; + int result; + + result = amfReadGroups (&error); + if (result == -1) { + printf ("Parse Error: %s\n", error); + exit (-1); + } + + saAmfPrintGroups (); + + return (0); +} diff --git a/test/testtimer.c b/test/testtimer.c index e69de29b..dfa42c83 100644 --- a/test/testtimer.c +++ b/test/testtimer.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2003-2004 MontaVista Software, Inc. + * + * All rights reserved. + * + * Author: Steven Dake (sdake@mvista.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 +#include +#include +#include + +#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); +}