Просмотр исходного кода

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

Steven Dake 20 лет назад
Родитель
Сommit
ca58a16b6b
3 измененных файлов с 391 добавлено и 30 удалено
  1. 27 22
      exec/clm.c
  2. 11 8
      test/Makefile
  3. 353 0
      test/testclm2.c

+ 27 - 22
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 (&notification.clusterNode, &clusterNodes[i],
 				sizeof (SaClmClusterNodeT));
 		}
 	}
 
-	library_notification_send (&clusterNotification, 1);
+	library_notification_send (&notification, 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);

+ 11 - 8
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 \

+ 353 - 0
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 <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <saClm.h>
+
+
+#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; i<name->length; 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; j<buffer->numberOfItems; 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";
+}