From ca58a16b6b875b9e80ccee2a70fc68d05da7e3bb Mon Sep 17 00:00:00 2001 From: Steven Dake Date: Tue, 30 Aug 2005 20:29:13 +0000 Subject: [PATCH] defect 841 Rabbe reported that cluster track callback operations dont work properly. This patch fixes that problem. git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@809 fd59a12c-fef9-0310-b244-a6a79926bd2f --- exec/clm.c | 49 ++++--- test/Makefile | 19 +-- test/testclm2.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 391 insertions(+), 30 deletions(-) create mode 100644 test/testclm2.c diff --git a/exec/clm.c b/exec/clm.c index 085c3ed9..79caddd2 100644 --- a/exec/clm.c +++ b/exec/clm.c @@ -241,6 +241,19 @@ void library_notification_send (SaClmClusterNotificationT *cluster_notification_ struct conn_info *conn_info; struct list_head *list; + if (notify_entries == 0) { + return; + } + + res_lib_clm_clustertrack.header.size = sizeof (struct res_lib_clm_clustertrack); + res_lib_clm_clustertrack.header.id = MESSAGE_RES_CLM_TRACKCALLBACK; + res_lib_clm_clustertrack.header.error = SA_OK; + res_lib_clm_clustertrack.viewNumber = 0; + res_lib_clm_clustertrack.numberOfItems = notify_entries; + memcpy (&res_lib_clm_clustertrack.notification, + cluster_notification_entries, + sizeof (SaClmClusterNotificationT) * notify_entries); + for (list = library_notification_send_listhead.next; list != &library_notification_send_listhead; list = list->next) { @@ -250,39 +263,29 @@ void library_notification_send (SaClmClusterNotificationT *cluster_notification_ /* * Send notifications to all CLM listeners */ - if (notify_entries) { - res_lib_clm_clustertrack.header.size = sizeof (struct res_lib_clm_clustertrack) + - (notify_entries * sizeof (SaClmClusterNotificationT)); - res_lib_clm_clustertrack.header.id = MESSAGE_RES_CLM_TRACKCALLBACK; - res_lib_clm_clustertrack.header.error = SA_OK; - res_lib_clm_clustertrack.viewNumber = 0; - res_lib_clm_clustertrack.numberOfItems = notify_entries; - libais_send_response (conn_info, &res_lib_clm_clustertrack, - sizeof (struct res_lib_clm_clustertrack)); - libais_send_response (conn_info, cluster_notification_entries, - sizeof (SaClmClusterNotificationT) * notify_entries); - } + libais_send_response (conn_info, &res_lib_clm_clustertrack, + sizeof (struct res_lib_clm_clustertrack)); } } -static void libraryNotificationJoin (SaClmNodeIdT node) +static void notification_join (SaClmNodeIdT node) { - SaClmClusterNotificationT clusterNotification; + SaClmClusterNotificationT notification; int i; /* * Generate notification element */ - clusterNotification.clusterChange = SA_CLM_NODE_JOINED; - clusterNotification.clusterNode.member = 1; + notification.clusterChange = SA_CLM_NODE_JOINED; + notification.clusterNode.member = 1; for (i = 0; i < clusterNodeEntries; i++) { if (node == clusterNodes[i].nodeId) { - memcpy (&clusterNotification.clusterNode, &clusterNodes[i], + memcpy (¬ification.clusterNode, &clusterNodes[i], sizeof (SaClmClusterNodeT)); } } - library_notification_send (&clusterNotification, 1); + library_notification_send (¬ification, 1); } static void libraryNotificationLeave (SaClmNodeIdT *nodes, int nodes_entries) @@ -385,10 +388,12 @@ static int clm_confchg_fn ( * transitioning to network interface up or down */ 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 ((char *)thisClusterNode.nodeName.value, (char *)inet_ntoa (this_ip->sin_addr)); + + sprintf (thisClusterNode.nodeAddress.value, "%s", inet_ntoa (this_ip->sin_addr)); + thisClusterNode.nodeAddress.length = strlen (thisClusterNode.nodeAddress.value); + thisClusterNode.nodeAddress.family = SA_CLM_AF_INET; + sprintf (thisClusterNode.nodeName.value, "%s", inet_ntoa (this_ip->sin_addr)); thisClusterNode.nodeName.length = strlen ((char *)thisClusterNode.nodeName.value); return (0); @@ -479,7 +484,7 @@ static int message_handler_req_exec_clm_nodejoin (void *message, struct in_addr sizeof (SaClmClusterNodeT)); clusterNodeEntries += 1; - libraryNotificationJoin (req_exec_clm_nodejoin->clusterNode.nodeId); + notification_join (req_exec_clm_nodejoin->clusterNode.nodeId); } return (0); diff --git a/test/Makefile b/test/Makefile index 6d9a0b29..e53bb266 100644 --- a/test/Makefile +++ b/test/Makefile @@ -32,16 +32,16 @@ LIBRARIES= ../lib/libSaClm.a ../lib/libSaAmf.a ../lib/libSaCkpt.a ../lib/libSaEv LIBS = $(LIBRARIES) -lpthread # Production mode flags -CFLAGS = -c -O3 -Wall -I../include -CFLAGS = -c -O3 -Wall -I../include -LDFLAGS = -L../lib +#CFLAGS = -c -O3 -Wall -I../include +#CFLAGS = -c -O3 -Wall -I../include +#LDFLAGS = -L../lib #LIBRARIES= ../lib/libais.a ../lib/libevs.a #LIBS = $(LIBRARIES) -lpthread # Debug mode flags -#CFLAGS = -c -g -Wall -DDEBUG -I../include -#CPPFLAGS = -c -g -Wall -DDEBUG -I../include -#LDFLAGS = -g -L../lib +CFLAGS = -c -g -Wall -DDEBUG -I../include +CPPFLAGS = -c -g -Wall -DDEBUG -I../include +LDFLAGS = -g -L../lib # Profile mode flags #CFLAGS = -c -O3 -pg -DDEBUG -I../include @@ -53,12 +53,12 @@ TEST_SRC = testclm.c testamf.c testamf1.c testamf2.c testamf3.c \ testckpt.c ckptstress.c ckptbench.c \ ckptbenchth.c testevt.c testevs.c evsbench.c \ subscription.c publish.c evtbench.c \ - sa_error.c unlink.c + sa_error.c unlink.c testclm2.c all: testclm testamf testamf1 testamf2 testamf3 testamf4 testamf5 \ testamf6 testamfth testckpt ckptstress ckptbench \ ckptbenchth ckpt-rd ckpt-wr testevt testevs \ - evsbench subscription publish evtbench unlink + evsbench subscription publish evtbench unlink testclm2 testtimer: testtimer.o $(LIBRARIES) $(CC) $(LDFLAGS) -o testtimer testtimer.o ../exec/timer.o @@ -135,6 +135,9 @@ ckpt-rd: ckpt-rd.o sa_error.o $(LIBRARIES) ckpt-wr: ckpt-wr.o sa_error.o $(LIBRARIES) $(CC) $(LDFLAGS) -o ckpt-wr ckpt-wr.o sa_error.o $(LIBS) +testclm2: testclm2.o $(LIBRARIES) + $(CC) $(LDFLAGS) -o testclm2 testclm2.o $(LIBS) + clean: rm -f *.o testclm testamf testamf1 testamf2 testamf3 testamf4 \ testamf5 testamf6 testamfth testckpt ckptstress testtimer \ diff --git a/test/testclm2.c b/test/testclm2.c new file mode 100644 index 00000000..b7f6eb47 --- /dev/null +++ b/test/testclm2.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2005 Ericsson AB + * + * All rights reserved. + * + * Author: Rabbe Fogelholm (rabbe.fogelholm@ericsson.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. + */ + +/* + * testclm2.c + * + * Simple program to test cluster membership on an SA Forum platform. + * The program expects one command-line argument which is "query" + * or "callback". "Query" means that a single saClmClusterTrack call + * is to be made. "Callback" means that callbacks are wanted when + * there are changes in cluster membership. At least a 2-node cluster + * is required to test this program mode. + * + * Tested on platforms: + * Gentoo Linux 2005-08 (build) + * Fedora Core 4 (build and run) + * + * Change history: + * 2005-08-28 Rabbe Fogelholm: + * Initial version + * 2005-08-30 Rabbe Fogelholm: + * Added call to saClmClusterTrackStop() + * Possible to test SA_TRACK_CHANGES_ONLY + * Improved diagnostics + */ + + +#include +#include +#include +#include +#include +#include + +#include + + +#define PGM_NAME "testclm2" + +#define MODE_QUERY 1 +#define MODE_CALLBACK 2 +#define MODE_UNKNOWN -1 + + +SaClmHandleT handle; + +int mode = MODE_UNKNOWN; + + +void interruptAction(); + +void usage(); + +void clusterTrack(const SaClmClusterNotificationBufferT *, SaUint32T, SaAisErrorT); + +int apiCall(char *, SaAisErrorT); + +char *decodeStatus(int); + +void printBoolean(SaBoolT); + +void printName(SaNameT *); + +void printAddress(SaClmNodeAddressT *); + +void printCluster(const SaClmClusterNotificationBufferT *); + +void printDate(SaTimeT); + +char *decodeClusterChange(int); + + +int main(int argc, char *argv[]) +{ + struct sigaction act; + act.sa_handler = interruptAction; + int status; + if ((status = sigaction(SIGINT, &act, NULL)) != 0) + { + printf("sigaction returned: %d\n", status); + } + + if (argc != 2 && argc != 3) + { + usage(); + return 1; + } + + mode = + strcmp(argv[1], "query") == 0 ? MODE_QUERY : + strcmp(argv[1], "callback") == 0 ? MODE_CALLBACK : + MODE_UNKNOWN; + if (mode == MODE_UNKNOWN) + { + usage(); + return 1; + } + + if (mode == MODE_CALLBACK && argc != 3) + { + usage(); + return 1; + } + int trackingMode = + mode == MODE_QUERY ? SA_TRACK_CURRENT : + mode == MODE_CALLBACK && strcmp(argv[2], "full") == 0 ? SA_TRACK_CHANGES : + mode == MODE_CALLBACK && strcmp(argv[2], "delta") == 0 ? SA_TRACK_CHANGES_ONLY : + -1; + if (trackingMode == -1) + { + usage(); + return 1; + } + + SaClmCallbacksT callbacks; + callbacks.saClmClusterNodeGetCallback = NULL; + callbacks.saClmClusterTrackCallback = (SaClmClusterTrackCallbackT)clusterTrack; + + SaVersionT version; + version.releaseCode = 'B'; + version.majorVersion = 1; + version.minorVersion = 0; + + + if (! apiCall("Initialize", saClmInitialize(&handle ,&callbacks, &version))) + return 1; + + printf("AIS version supported: %c.%d.%d\n", + version.releaseCode, version.majorVersion, version.minorVersion); + + if (mode == MODE_QUERY) + { + SaClmClusterNotificationBufferT buffer = {123456789, 123456789, NULL}; + apiCall("ClusterTrack", saClmClusterTrack(handle, trackingMode, &buffer)); + printCluster(&buffer); + free(buffer.notification); + } + + if (mode == MODE_CALLBACK) + { + printf("(type ctrl-C to finish)\n"); + apiCall("ClusterTrack", saClmClusterTrack(handle, trackingMode, NULL)); + while (1) + { + apiCall("Dispatch", saClmDispatch(handle, SA_DISPATCH_ONE)); + printf("sleep 1 sec\n"); + sleep(1); + } + } + + apiCall("Finalize", saClmFinalize(handle)); + return 0; +} + + +void interruptAction() +{ + fprintf(stderr, "SIGINT signal caught\n"); + if (mode == MODE_CALLBACK) + { + apiCall("ClusterTrackStop", handle); + } + apiCall("Finalize", saClmFinalize(handle)); + exit(0); +} + + +void usage() +{ + fprintf(stderr, "%s: usage is:\n", PGM_NAME); + fprintf(stderr, " membership query Query for membership once\n"); + fprintf(stderr, " membership callback full Callback on membership change, full report\n"); + fprintf(stderr, " membership callback delta Callback on membership change, delta report\n"); +} + + +void clusterTrack( + const SaClmClusterNotificationBufferT *buffer, + SaUint32T numberOfMembers, + SaAisErrorT error) +{ + apiCall("clusterTrack callback", error); + printf("number of members: %d\n\n", numberOfMembers); + printCluster(buffer); +} + + +int apiCall(char *call, SaAisErrorT code) +{ + char *s = decodeStatus(code); + printf("called: %s, status: %s", call, s); + if (strcmp(s, "unknown error code") == 0) + { + printf(": %d\n\n", code); + } + else + { + printf("\n\n"); + } + return code == SA_AIS_OK ? 1 : 0; +} + + +char *decodeStatus(int code) +{ + return + code == SA_AIS_OK ? "successful" : + code == SA_AIS_ERR_LIBRARY ? "error in library, cannot be used anymore" : + code == SA_AIS_ERR_VERSION ? "version incompatibility" : + code == SA_AIS_ERR_INIT ? "callback function has not been supplied" : + code == SA_AIS_ERR_TIMEOUT ? "timeout occurred, call may or may not have succeeded" : + code == SA_AIS_ERR_TRY_AGAIN ? "service cannot be provided now, try later" : + code == SA_AIS_ERR_INVALID_PARAM ? "a parameter is not set correctly" : + code == SA_AIS_ERR_NO_MEMORY ? "out of memory" : + code == SA_AIS_ERR_BAD_HANDLE ? "handle is invalid" : + code == SA_AIS_ERR_BUSY ? "resource already in use" : + code == SA_AIS_ERR_ACCESS ? "access denied" : + code == SA_AIS_ERR_NOT_EXIST ? "entity does not exist" : + code == SA_AIS_ERR_NAME_TOO_LONG ? "name too long" : + code == SA_AIS_ERR_EXIST ? "entity already exists" : + code == SA_AIS_ERR_NO_SPACE ? "buffer space is not sufficient" : + code == SA_AIS_ERR_INTERRUPT ? "request canceled by timeout or other interrupt" : + code == SA_AIS_ERR_NAME_NOT_FOUND ? "name not found" : + code == SA_AIS_ERR_NOT_SUPPORTED ? "requested function is not supported" : + code == SA_AIS_ERR_BAD_OPERATION ? "requested operation is not allowed" : + code == SA_AIS_ERR_FAILED_OPERATION ? "healthcheck unsuccessful, error callback done" : + code == SA_AIS_ERR_NO_RESOURCES ? "insufficient resources other than memory" : + code == SA_AIS_ERR_MESSAGE_ERROR ? "a communication error occurred" : + code == SA_AIS_ERR_QUEUE_FULL ? "destination queue is full" : + code == SA_AIS_ERR_QUEUE_NOT_AVAILABLE ? "destination queue not available" : + code == SA_AIS_ERR_BAD_FLAGS ? "flags are invalid" : + code == SA_AIS_ERR_TOO_BIG ? "value larger than maximum permitted" : + code == SA_AIS_ERR_NO_SECTIONS ? "no sections matching spec in SectionIteratorInitialize call" : + "unknown error code"; +} + + +void printBoolean(SaBoolT b) +{ + printf("%s\n", b ? "true" : "false"); +} + + +void printName(SaNameT *name) +{ + int i; + for (i=0; ilength; i++) printf("%c", name->value[i]); + printf("\n"); +} + + +void printAddress(SaClmNodeAddressT *nodeAddress) +{ + if (nodeAddress->family == SA_CLM_AF_INET6) + { + printf("sorry, cannot decode IPv6 yet\n"); + } + else if (nodeAddress->length == 4) + { + // we may get here due to defect 833, see + // http://www.osdl.org/developer_bugzilla/show_bug.cgi?id=833 for details + printf("%d.%d.%d.%d\n", + nodeAddress->value[0], + nodeAddress->value[1], + nodeAddress->value[2], + nodeAddress->value[3]); + } + else + { + int k; + for (k = 0; k < nodeAddress->length; k++) + { + printf("%c", nodeAddress->value[k]); + } + printf("\n"); + } +} + + +void printCluster(const SaClmClusterNotificationBufferT *buffer) +{ + printf(" view number: %llu\n", buffer->viewNumber); + printf(" number of items: %u\n\n", buffer->numberOfItems); + int j; for (j=0; jnumberOfItems; j++) + { + printf(" node index within sequence: %d\n", j); + printf(" cluster node: %u\n", buffer->notification[j].clusterNode.nodeId); + printf(" address: "); printAddress(& buffer->notification[j].clusterNode.nodeAddress); + printf(" name: "); printName(&(buffer->notification[j].clusterNode.nodeName)); + printf(" member: "); printBoolean(buffer->notification[j].clusterNode.member); + printf(" booted: "); printDate(buffer->notification[j].clusterNode.bootTimestamp); + printf(" initial view number: %llu\n", buffer->notification[j].clusterNode.initialViewNumber); + printf(" cluster change: %s\n", decodeClusterChange(buffer->notification[j].clusterChange)); + printf("\n"); + } +} + + +void printDate(SaTimeT nanoseconds) +{ + time_t tt = nanoseconds/SA_TIME_ONE_SECOND; + struct tm *decodedTime = localtime(&tt); + + printf("%d-%02d-%02d %02d:%02d:%02d\n", + decodedTime->tm_year + 1900, + decodedTime->tm_mon + 1, + decodedTime->tm_mday, + decodedTime->tm_hour, + decodedTime->tm_min, + decodedTime->tm_sec); +} + + +char *decodeClusterChange(int code) +{ + return + code == SA_CLM_NODE_NO_CHANGE ? "node has not changed" : + code == SA_CLM_NODE_JOINED ? "node has joined the cluster" : + code == SA_CLM_NODE_LEFT ? "node has left the cluster" : + code == SA_CLM_NODE_RECONFIGURED ? "node has been reconfigured" : + "unknown type of node change"; +}