mirror of
https://git.proxmox.com/git/mirror_corosync
synced 2025-06-11 01:31:42 +00:00

fix gcc 4 specific compile warnings and compile errors git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@834 fd59a12c-fef9-0310-b244-a6a79926bd2f
354 lines
11 KiB
C
354 lines
11 KiB
C
/*
|
|
* 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", saClmClusterTrackStop(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", (unsigned long long)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", (unsigned long long)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";
|
|
}
|