2 * Copyright (c) 2005 Ericsson AB
6 * Author: Rabbe Fogelholm (rabbe.fogelholm@ericsson.com)
8 * This software licensed under BSD license, the text of which follows:
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.
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)
50 * 2005-08-28 Rabbe Fogelholm:
52 * 2005-08-30 Rabbe Fogelholm:
53 * Added call to saClmClusterTrackStop()
54 * Possible to test SA_TRACK_CHANGES_ONLY
55 * Improved diagnostics
69 #define PGM_NAME "testclm2"
72 #define MODE_CALLBACK 2
73 #define MODE_UNKNOWN -1
78 int mode
= MODE_UNKNOWN
;
81 void interruptAction();
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
;
109 if ((status
= sigaction(SIGINT
, &act
, NULL
)) != 0)
111 printf("sigaction returned: %d\n", status
);
114 if (argc
!= 2 && argc
!= 3)
121 strcmp(argv
[1], "query") == 0 ? MODE_QUERY
:
122 strcmp(argv
[1], "callback") == 0 ? MODE_CALLBACK
:
124 if (mode
== MODE_UNKNOWN
)
130 if (mode
== MODE_CALLBACK
&& argc
!= 3)
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)
146 SaClmCallbacksT callbacks
;
147 callbacks
.saClmClusterNodeGetCallback
= NULL
;
148 callbacks
.saClmClusterTrackCallback
= (SaClmClusterTrackCallbackT
)clusterTrack
;
151 version
.releaseCode
= 'B';
152 version
.majorVersion
= 1;
153 version
.minorVersion
= 0;
156 if (! apiCall("Initialize", saClmInitialize(&handle
,&callbacks
, &version
)))
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
));
176 apiCall("Dispatch", saClmDispatch(handle
, SA_DISPATCH_ONE
));
177 printf("sleep 1 sec\n");
182 apiCall("Finalize", saClmFinalize(handle
));
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
));
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");
209 const SaClmClusterNotificationBufferT
*buffer
,
210 SaUint32T numberOfMembers
,
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
);
231 return code
== SA_AIS_OK
? 1 : 0;
235 char *decodeStatus(int code
)
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
)
278 for (i
=0; i
<name
->length
; i
++) printf("%c", name
->value
[i
]);
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]);
302 for (k
= 0; k
< nodeAddress
->length
; k
++)
304 printf("%c", nodeAddress
->value
[k
]);
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
));
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
,
341 decodedTime
->tm_sec
);
345 char *decodeClusterChange(int code
)
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";