Patch to reinitialize logsys internal variables after a fork for correct
[openais.git] / test / testclm2.c
blob9c1b2ea9f729f0c0d430c0bd01ea472efcddc87d
1 /*
2 * Copyright (c) 2005 Ericsson AB
4 * All rights reserved.
6 * Author: Rabbe Fogelholm (rabbe.fogelholm@ericsson.com)
8 * This software licensed under BSD license, the text of which follows:
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 * - Neither the name of the MontaVista Software, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived from this
20 * software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
36 * testclm2.c
38 * Simple program to test cluster membership on an SA Forum platform.
39 * The program expects one command-line argument which is "query"
40 * or "callback". "Query" means that a single saClmClusterTrack call
41 * is to be made. "Callback" means that callbacks are wanted when
42 * there are changes in cluster membership. At least a 2-node cluster
43 * is required to test this program mode.
45 * Tested on platforms:
46 * Gentoo Linux 2005-08 (build)
47 * Fedora Core 4 (build and run)
49 * Change history:
50 * 2005-08-28 Rabbe Fogelholm:
51 * Initial version
52 * 2005-08-30 Rabbe Fogelholm:
53 * Added call to saClmClusterTrackStop()
54 * Possible to test SA_TRACK_CHANGES_ONLY
55 * Improved diagnostics
56 */
59 #include <stdio.h>
60 #include <string.h>
61 #include <signal.h>
62 #include <stdlib.h>
63 #include <unistd.h>
64 #include <time.h>
66 #include <saClm.h>
69 #define PGM_NAME "testclm2"
71 #define MODE_QUERY 1
72 #define MODE_CALLBACK 2
73 #define MODE_UNKNOWN -1
76 SaClmHandleT handle;
78 int mode = MODE_UNKNOWN;
81 void interruptAction();
83 void usage();
85 void clusterTrack(const SaClmClusterNotificationBufferT *, SaUint32T, SaAisErrorT);
87 int apiCall(char *, SaAisErrorT);
89 char *decodeStatus(int);
91 void printBoolean(SaBoolT);
93 void printName(SaNameT *);
95 void printAddress(SaClmNodeAddressT *);
97 void printCluster(const SaClmClusterNotificationBufferT *);
99 void printDate(SaTimeT);
101 char *decodeClusterChange(int);
104 int main(int argc, char *argv[])
106 struct sigaction act;
107 act.sa_handler = interruptAction;
108 int status;
109 if ((status = sigaction(SIGINT, &act, NULL)) != 0)
111 printf("sigaction returned: %d\n", status);
114 if (argc != 2 && argc != 3)
116 usage();
117 return 1;
120 mode =
121 strcmp(argv[1], "query") == 0 ? MODE_QUERY :
122 strcmp(argv[1], "callback") == 0 ? MODE_CALLBACK :
123 MODE_UNKNOWN;
124 if (mode == MODE_UNKNOWN)
126 usage();
127 return 1;
130 if (mode == MODE_CALLBACK && argc != 3)
132 usage();
133 return 1;
135 int trackingMode =
136 mode == MODE_QUERY ? SA_TRACK_CURRENT :
137 mode == MODE_CALLBACK && strcmp(argv[2], "full") == 0 ? SA_TRACK_CHANGES :
138 mode == MODE_CALLBACK && strcmp(argv[2], "delta") == 0 ? SA_TRACK_CHANGES_ONLY :
140 if (trackingMode == -1)
142 usage();
143 return 1;
146 SaClmCallbacksT callbacks;
147 callbacks.saClmClusterNodeGetCallback = NULL;
148 callbacks.saClmClusterTrackCallback = (SaClmClusterTrackCallbackT)clusterTrack;
150 SaVersionT version;
151 version.releaseCode = 'B';
152 version.majorVersion = 1;
153 version.minorVersion = 0;
156 if (! apiCall("Initialize", saClmInitialize(&handle ,&callbacks, &version)))
157 return 1;
159 printf("AIS version supported: %c.%d.%d\n",
160 version.releaseCode, version.majorVersion, version.minorVersion);
162 if (mode == MODE_QUERY)
164 SaClmClusterNotificationBufferT buffer = {123456789, 123456789, NULL};
165 apiCall("ClusterTrack", saClmClusterTrack(handle, trackingMode, &buffer));
166 printCluster(&buffer);
167 free(buffer.notification);
170 if (mode == MODE_CALLBACK)
172 printf("(type ctrl-C to finish)\n");
173 apiCall("ClusterTrack", saClmClusterTrack(handle, trackingMode, NULL));
174 while (1)
176 apiCall("Dispatch", saClmDispatch(handle, SA_DISPATCH_ONE));
177 printf("sleep 1 sec\n");
178 sleep(1);
182 apiCall("Finalize", saClmFinalize(handle));
183 return 0;
187 void interruptAction()
189 fprintf(stderr, "SIGINT signal caught\n");
190 if (mode == MODE_CALLBACK)
192 apiCall("ClusterTrackStop", saClmClusterTrackStop(handle));
194 apiCall("Finalize", saClmFinalize(handle));
195 exit(0);
199 void usage()
201 fprintf(stderr, "%s: usage is:\n", PGM_NAME);
202 fprintf(stderr, " membership query Query for membership once\n");
203 fprintf(stderr, " membership callback full Callback on membership change, full report\n");
204 fprintf(stderr, " membership callback delta Callback on membership change, delta report\n");
208 void clusterTrack(
209 const SaClmClusterNotificationBufferT *buffer,
210 SaUint32T numberOfMembers,
211 SaAisErrorT error)
213 apiCall("clusterTrack callback", error);
214 printf("number of members: %d\n\n", numberOfMembers);
215 printCluster(buffer);
219 int apiCall(char *call, SaAisErrorT code)
221 char *s = decodeStatus(code);
222 printf("called: %s, status: %s", call, s);
223 if (strcmp(s, "unknown error code") == 0)
225 printf(": %d\n\n", code);
227 else
229 printf("\n\n");
231 return code == SA_AIS_OK ? 1 : 0;
235 char *decodeStatus(int code)
237 return
238 code == SA_AIS_OK ? "successful" :
239 code == SA_AIS_ERR_LIBRARY ? "error in library, cannot be used anymore" :
240 code == SA_AIS_ERR_VERSION ? "version incompatibility" :
241 code == SA_AIS_ERR_INIT ? "callback function has not been supplied" :
242 code == SA_AIS_ERR_TIMEOUT ? "timeout occurred, call may or may not have succeeded" :
243 code == SA_AIS_ERR_TRY_AGAIN ? "service cannot be provided now, try later" :
244 code == SA_AIS_ERR_INVALID_PARAM ? "a parameter is not set correctly" :
245 code == SA_AIS_ERR_NO_MEMORY ? "out of memory" :
246 code == SA_AIS_ERR_BAD_HANDLE ? "handle is invalid" :
247 code == SA_AIS_ERR_BUSY ? "resource already in use" :
248 code == SA_AIS_ERR_ACCESS ? "access denied" :
249 code == SA_AIS_ERR_NOT_EXIST ? "entity does not exist" :
250 code == SA_AIS_ERR_NAME_TOO_LONG ? "name too long" :
251 code == SA_AIS_ERR_EXIST ? "entity already exists" :
252 code == SA_AIS_ERR_NO_SPACE ? "buffer space is not sufficient" :
253 code == SA_AIS_ERR_INTERRUPT ? "request canceled by timeout or other interrupt" :
254 code == SA_AIS_ERR_NAME_NOT_FOUND ? "name not found" :
255 code == SA_AIS_ERR_NOT_SUPPORTED ? "requested function is not supported" :
256 code == SA_AIS_ERR_BAD_OPERATION ? "requested operation is not allowed" :
257 code == SA_AIS_ERR_FAILED_OPERATION ? "healthcheck unsuccessful, error callback done" :
258 code == SA_AIS_ERR_NO_RESOURCES ? "insufficient resources other than memory" :
259 code == SA_AIS_ERR_MESSAGE_ERROR ? "a communication error occurred" :
260 code == SA_AIS_ERR_QUEUE_FULL ? "destination queue is full" :
261 code == SA_AIS_ERR_QUEUE_NOT_AVAILABLE ? "destination queue not available" :
262 code == SA_AIS_ERR_BAD_FLAGS ? "flags are invalid" :
263 code == SA_AIS_ERR_TOO_BIG ? "value larger than maximum permitted" :
264 code == SA_AIS_ERR_NO_SECTIONS ? "no sections matching spec in SectionIteratorInitialize call" :
265 "unknown error code";
269 void printBoolean(SaBoolT b)
271 printf("%s\n", b ? "true" : "false");
275 void printName(SaNameT *name)
277 int i;
278 for (i=0; i<name->length; i++) printf("%c", name->value[i]);
279 printf("\n");
283 void printAddress(SaClmNodeAddressT *nodeAddress)
285 if (nodeAddress->family == SA_CLM_AF_INET6)
287 printf("sorry, cannot decode IPv6 yet\n");
289 else if (nodeAddress->length == 4)
291 // we may get here due to defect 833, see
292 // http://www.osdl.org/developer_bugzilla/show_bug.cgi?id=833 for details
293 printf("%d.%d.%d.%d\n",
294 nodeAddress->value[0],
295 nodeAddress->value[1],
296 nodeAddress->value[2],
297 nodeAddress->value[3]);
299 else
301 int k;
302 for (k = 0; k < nodeAddress->length; k++)
304 printf("%c", nodeAddress->value[k]);
306 printf("\n");
311 void printCluster(const SaClmClusterNotificationBufferT *buffer)
313 printf(" view number: %llu\n", (unsigned long long)buffer->viewNumber);
314 printf(" number of items: %u\n\n", buffer->numberOfItems);
315 int j; for (j=0; j<buffer->numberOfItems; j++)
317 printf(" node index within sequence: %d\n", j);
318 printf(" cluster node: %u\n", buffer->notification[j].clusterNode.nodeId);
319 printf(" address: "); printAddress(& buffer->notification[j].clusterNode.nodeAddress);
320 printf(" name: "); printName(&(buffer->notification[j].clusterNode.nodeName));
321 printf(" member: "); printBoolean(buffer->notification[j].clusterNode.member);
322 printf(" booted: "); printDate(buffer->notification[j].clusterNode.bootTimestamp);
323 printf(" initial view number: %llu\n", (unsigned long long)buffer->notification[j].clusterNode.initialViewNumber);
324 printf(" cluster change: %s\n", decodeClusterChange(buffer->notification[j].clusterChange));
325 printf("\n");
330 void printDate(SaTimeT nanoseconds)
332 time_t tt = nanoseconds/SA_TIME_ONE_SECOND;
333 struct tm *decodedTime = localtime(&tt);
335 printf("%d-%02d-%02d %02d:%02d:%02d\n",
336 decodedTime->tm_year + 1900,
337 decodedTime->tm_mon + 1,
338 decodedTime->tm_mday,
339 decodedTime->tm_hour,
340 decodedTime->tm_min,
341 decodedTime->tm_sec);
345 char *decodeClusterChange(int code)
347 return
348 code == SA_CLM_NODE_NO_CHANGE ? "node has not changed" :
349 code == SA_CLM_NODE_JOINED ? "node has joined the cluster" :
350 code == SA_CLM_NODE_LEFT ? "node has left the cluster" :
351 code == SA_CLM_NODE_RECONFIGURED ? "node has been reconfigured" :
352 "unknown type of node change";