2 * Copyright (c) 2002-2003 MontaVista Software, Inc.
3 * Copyright (c) 2006 Ericsson AB.
4 * Copyright (c) 2006 Sun Microsystems, Inc.
8 * Author: Steven Dake (sdake@mvista.com)
11 * This software licensed under BSD license, the text of which follows:
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions are met:
16 * - Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * - Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 * - Neither the name of the MontaVista Software, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
44 #include <sys/types.h>
45 #include <sys/socket.h>
57 SaAmfHealthcheckKeyT keyAmfInvoked
= {
62 SaAmfHealthcheckKeyT keyCompInvoked
= {
67 SaNameT compNameGlobal
;
69 int good_health_limit
= 0;
77 #define die(format, args...) _die (__FILE__, __LINE__, format, ##args)
79 static void _die (char *file
, int line
, char *format
, ...) __attribute__((format(printf
, 3, 4)));
80 static void _die (char *file
, int line
, char *format
, ...)
85 sprintf (buf
, "%d - %s:#%d - Error: '%s', exiting...\n",
86 (int)getpid(), file
, line
, format
);
88 va_start (ap
, format
);
89 vfprintf (stderr
, buf
, ap
);
95 static void response (
96 SaAmfHandleT handle
, SaInvocationT invocation
, SaAisErrorT error
)
101 result
= saAmfResponse (handle
, invocation
, error
);
102 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
103 fprintf(stderr
, "%d: TRY_AGAIN received\n", (int)getpid());
106 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
107 if (result
!= SA_AIS_OK
) {
108 die ("saAmfResponse failed %d", result
);
112 void printSaNameT (SaNameT
*name
)
116 for (i
= 0; i
< name
->length
; i
++) {
117 printf ("%c", name
->value
[i
]);
121 void setSanameT (SaNameT
*name
, char *str
) {
122 name
->length
= strlen (str
);
123 memcpy (name
->value
, str
, name
->length
);
126 static unsigned int healthcheck_no
= 0;
130 void HealthcheckCallback (SaInvocationT invocation
,
131 const SaNameT
*compName
,
132 SaAmfHealthcheckKeyT
*healthcheckKey
)
136 if( !good_health
&& healthcheck_no
++);
138 if (healthcheck_no
== good_health_limit
) {
139 response (handle
, invocation
, SA_AIS_OK
);
140 res
= saAmfHealthcheckStop (handle
,
143 printf ("healthcheck stop result %d (should be %d)\n", res
, SA_AIS_OK
);
145 printf ("COMPONENT REPORTING ERROR %s\n", compNameGlobal
.value
);
146 saAmfComponentErrorReport (handle
, compName
, 0, SA_AMF_COMPONENT_RESTART
, 0);
147 printf ("COMPONENT DONE REPORTING ERROR\n");
149 response (handle
, invocation
, SA_AIS_OK
);
153 void ComponentTerminateCallback (
154 SaInvocationT invocation
,
155 const SaNameT
*compName
)
157 printf ("ComponentTerminateCallback\n");
158 response (handle
, invocation
, SA_AIS_OK
);
163 #include <sys/time.h>
166 #define TR(format,x) do { \
168 gettimeofday(&t,NULL); \
169 printf("%s:%d: %s : %d : %u: %u :%s : " format "\n",\
170 __FILE__,__LINE__,__FUNCTION__, \
171 (int)getpid(),(int)t.tv_sec, (int)t.tv_usec,#x,x); \
179 void CSISetCallback (
180 SaInvocationT invocation
,
181 const SaNameT
*compName
,
182 SaAmfHAStateT haState
,
183 SaAmfCSIDescriptorT
*csiDescriptor
)
190 case SA_AMF_HA_ACTIVE
:
191 printf ("PID %d: Component '%s' requested to enter hastate SA_AMF_ACTIVE"
192 " for \n\tCSI '%s'\n",
193 (int)getpid(), compName
->value
, csiDescriptor
->csiName
.value
);
194 response (handle
, invocation
, SA_AIS_OK
);
196 res
= saAmfHAStateGet (handle
, compName
, &csiDescriptor
->csiName
, &state
);
197 if (res
!= SA_AIS_OK
|| haState
!= state
) {
198 fprintf (stderr
, "saAmfHAStateGet failed: %d\n", res
);
202 TR(TRU
, csiDescriptor
->csiAttr
.number
);
203 for(i
=0; i
<csiDescriptor
->csiAttr
.number
; i
++) {
205 if( strcmp((char*)csiDescriptor
->csiAttr
.attr
[i
].attrName
, "good_health_limit") == 0){
206 good_health
= strcmp((char*)csiDescriptor
->csiAttr
.attr
[i
].attrValue
, "0") ? 0 : 1;
207 good_health_limit
= atoi((char*)csiDescriptor
->csiAttr
.attr
[i
].attrValue
);
211 TR(TRS
,csiDescriptor
->csiAttr
.attr
[i
].attrName
);
212 TR(TRS
, csiDescriptor
->csiAttr
.attr
[i
].attrValue
);
216 TR(TRU
, csiDescriptor
->csiFlags
);
219 printSaNameT((SaNameT
*) &csiDescriptor
->csiStateDescriptor
.activeDescriptor
.activeCompName
);
220 TR(TRU
, csiDescriptor
->csiStateDescriptor
.activeDescriptor
.transitionDescriptor
);
224 case SA_AMF_HA_STANDBY
:
225 printf ("PID %d: Component '%s' requested to enter hastate SA_AMF_STANDBY "
226 "for \n\tCSI '%s'\n",
227 (int)getpid(), compName
->value
, csiDescriptor
->csiName
.value
);
228 response (handle
, invocation
, SA_AIS_OK
);
230 TR(TRU
,csiDescriptor
->csiAttr
.number
);
231 for(i
=0; i
<csiDescriptor
->csiAttr
.number
; i
++) {
232 if(!strcmp((char*)csiDescriptor
->csiAttr
.attr
[i
].attrName
, "good_health") &&
233 !strcmp((char*)csiDescriptor
->csiAttr
.attr
[i
].attrValue
, "true")){
236 TR(TRS
,csiDescriptor
->csiAttr
.attr
[i
].attrName
);
237 TR(TRS
,csiDescriptor
->csiAttr
.attr
[i
].attrValue
);
239 TR(TRU
,csiDescriptor
->csiFlags
);
241 printSaNameT((SaNameT
*) &csiDescriptor
->csiStateDescriptor
.standbyDescriptor
.activeCompName
);
242 TR(TRU
,csiDescriptor
->csiStateDescriptor
.standbyDescriptor
.standbyRank
);
245 case SA_AMF_HA_QUIESCED
:
246 printf ("%d: Component '%s' requested to enter hastate SA_AMF_HA_QUIESCED "
247 "for \n\tCSI '%s'\n",
248 (int)getpid(), compName
->value
, csiDescriptor
->csiName
.value
);
249 response (handle
, invocation
, SA_AIS_OK
);
251 case SA_AMF_HA_QUIESCING
:
258 void CSIRemoveCallback (
259 SaInvocationT invocation
,
260 const SaNameT
*compName
,
261 const SaNameT
*csiName
,
262 SaAmfCSIFlagsT csiFlags
)
264 printf ("CSIRemoveCallback for component '");
265 printSaNameT ((SaNameT
*)compName
);
266 printf ("' in CSI '");
267 printSaNameT ((SaNameT
*)csiName
);
269 response (handle
, invocation
, SA_AIS_OK
);
273 void ProtectionGroupTrackCallback (
274 const SaNameT
*csiName
,
275 SaAmfProtectionGroupNotificationT
*notificationBuffer
,
276 SaUint32T numberOfItems
,
277 SaUint32T numberOfMembers
,
282 printf ("ProtectionGroupTrackCallback items %d members %d\n", (int)numberOfItems
, (int)numberOfMembers
);
283 printf ("buffer is %p\n", notificationBuffer
);
284 for (i
= 0; i
< numberOfItems
; i
++) {
285 printf ("component name");
286 printSaNameT (¬ificationBuffer
[i
].member
.compName
);
288 printf ("\treadiness state is %d\n", notificationBuffer
[i
].member
.readinessState
);
289 printf ("\thastate %d\n", notificationBuffer
[i
].member
.haState
);
290 printf ("\tchange is %d\n", notificationBuffer
[i
].change
);
297 SaAmfCallbacksT amfCallbacks
= {
298 .saAmfHealthcheckCallback
= HealthcheckCallback
,
299 .saAmfComponentTerminateCallback
= ComponentTerminateCallback
,
300 .saAmfCSISetCallback
= CSISetCallback
,
301 .saAmfCSIRemoveCallback
= CSIRemoveCallback
,
304 SaAmfCallbacksT amfCallbacks
;
306 SaVersionT version
= { 'B', 1, 1 };
307 #if ! defined(TS_CLASS) && (defined(OPENAIS_BSD) || defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS))
308 static struct sched_param sched_param
;
311 void sigintr_handler (int signum
) {
315 void sigusr1_handler (int signum
) {
319 void sigusr2_handler (int signum
) {
323 void write_pid (void) {
329 sprintf (filename
, "/var/run/openais_cleanup_%s", compNameGlobal
.value
);
330 fd
= open (filename
, O_CREAT
| O_TRUNC
| O_RDWR
, S_IRWXU
);
332 printf("%d: Failed using /var/run for pid file, using /tmp\n", (int)getpid());
333 sprintf (filename
, "/tmp/openais_cleanup_%s", compNameGlobal
.value
);
334 fd
= open (filename
, O_CREAT
| O_TRUNC
| O_RDWR
, S_IRWXU
);
336 sprintf (pid
, "%d", (int)getpid());
337 res
= write (fd
, pid
, strlen (pid
));
341 static SaSelectionObjectT
comp_init ()
346 SaSelectionObjectT select_fd
;
347 SaAmfPmErrorsT pmErrors
= (SA_AMF_PM_ZERO_EXIT
|
348 SA_AMF_PM_NON_ZERO_EXIT
|
349 SA_AMF_PM_ABNORMAL_END
);
351 name
= getenv ("SA_AMF_COMPONENT_NAME");
353 die ("SA_AMF_COMPONENT_NAME missing");
356 if (strstr (name
, "safComp=") == NULL
||
357 strstr (name
, "safSu=") == NULL
||
358 strstr (name
, "safSg=") == NULL
||
359 strstr (name
, "safApp=") == NULL
) {
360 die ("SA_AMF_COMPONENT_NAME value wrong");
363 printf("%d: Hello world from %s\n", (int)getpid(), name
);
365 env
= getenv ("var1");
367 die ("var1 missing");
369 if (strcmp (env
, "val1") != 0) {
370 die ("var1 value wrong");
372 env
= getenv ("var2");
376 if (strcmp (env
, "val2") != 0) {
377 die ("var2 value wrong");
380 signal (SIGINT
, sigintr_handler
);
381 signal (SIGUSR1
, sigusr1_handler
);
382 signal (SIGUSR2
, sigusr2_handler
);
384 #if ! defined(TS_CLASS) && (defined(OPENAIS_BSD) || defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS))
386 sched_param
.sched_priority
= sched_get_priority_max(SCHED_RR
);
387 if (sched_param
.sched_priority
== -1) {
388 fprintf (stderr
, "%d: couldn't retrieve the maximum scheduling " \
389 "priority supported by the Round-Robin class (%s)\n",
390 (int)getpid(), strerror(errno
));
392 result
= sched_setscheduler (0, SCHED_RR
, &sched_param
);
394 fprintf (stderr
, "%d: couldn't set sched priority (%s)\n",
395 (int)getpid(), strerror(errno
));
401 result
= saAmfInitialize (&handle
, &amfCallbacks
, &version
);
402 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
403 printf("%d: TRY_AGAIN received\n", (int)getpid());
406 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
407 if (result
!= SA_AIS_OK
) {
408 die ("saAmfInitialize result is %d", result
);
412 result
= saAmfSelectionObjectGet (handle
, &select_fd
);
413 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
414 printf("%d: TRY_AGAIN received\n", (int)getpid());
417 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
418 if (result
!= SA_AIS_OK
) {
419 die ("saAmfSelectionObjectGet failed %d", result
);
423 result
= saAmfComponentNameGet (handle
, &compNameGlobal
);
424 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
425 printf("%d: TRY_AGAIN received\n", (int)getpid());
428 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
429 if (result
!= SA_AIS_OK
) {
430 die ("saAmfComponentNameGet failed %d", result
);
435 result
= saAmfHealthcheckStart (handle
,
438 SA_AMF_HEALTHCHECK_AMF_INVOKED
,
439 SA_AMF_COMPONENT_FAILOVER
);
440 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
441 printf("%d: TRY_AGAIN received\n", (int)getpid());
444 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
445 if (result
!= SA_AIS_OK
) {
446 die ("saAmfHealthcheckStart failed %d", result
);
450 result
= saAmfHealthcheckStart (handle
,
453 SA_AMF_HEALTHCHECK_COMPONENT_INVOKED
,
454 SA_AMF_COMPONENT_FAILOVER
);
455 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
456 printf("%d: TRY_AGAIN received\n", (int)getpid());
459 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
460 if (result
!= SA_AIS_OK
) {
461 die ("saAmfHealthcheckStart failed %d", result
);
466 strcpy ((char*)badname
.value
, "badname");
469 result
= saAmfComponentRegister (handle
, &badname
, NULL
);
470 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
471 printf("%d: TRY_AGAIN received\n", (int)getpid());
474 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
475 if (result
!= SA_AIS_ERR_INVALID_PARAM
) {
476 die ("saAmfComponentRegister failed %d", result
);
481 result
= saAmfComponentRegister (handle
, &compNameGlobal
, NULL
);
482 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
483 printf("%d: TRY_AGAIN received\n", (int)getpid());
486 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
487 if (result
!= SA_AIS_OK
) {
488 die ("saAmfComponentRegister failed %d", result
);
492 * startup passive monitoring
495 result
= saAmfPmStart (handle
,
496 &compNameGlobal
, getpid(), 1,
498 SA_AMF_COMPONENT_FAILOVER
);
500 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
501 printf("%d: TRY_AGAIN received\n", (int)getpid());
504 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
507 * Test already started healthcheck
510 result
= saAmfHealthcheckStart (handle
,
513 SA_AMF_HEALTHCHECK_AMF_INVOKED
,
514 SA_AMF_COMPONENT_FAILOVER
);
515 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
516 printf("%d: TRY_AGAIN received\n", (int)getpid());
519 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
520 if (result
!= SA_AIS_ERR_EXIST
) {
521 die ("saAmfHealthcheckStart failed %d", result
);
527 static void handle_intr (void)
533 result
= saAmfFinalize (handle
);
534 if (result
!= SA_AIS_OK
) {
535 die ("saAmfFinalize failed %d", result
);
537 fprintf(stderr
, "%d: %s exiting\n",
538 (int)getpid(), compNameGlobal
.value
);
542 fprintf(stderr
, "%d: %s unregistering\n",
543 (int)getpid(), compNameGlobal
.value
);
544 result
= saAmfComponentUnregister (
545 handle
, &compNameGlobal
, NULL
);
546 if (result
!= SA_AIS_OK
) {
547 die ("saAmfComponentUnregister failed %d", result
);
549 fprintf(stderr
, "%d: waiting after unregister\n", (int)getpid());
555 fprintf(stderr
, "%d: %s error reporting\n",
556 (int)getpid(), compNameGlobal
.value
);
557 result
= saAmfComponentErrorReport (
558 handle
, &compNameGlobal
, 0, SA_AMF_COMPONENT_RESTART
, 0);
559 if (result
!= SA_AIS_OK
) {
560 die ("saAmfComponentErrorReport failed %d", result
);
562 fprintf(stderr
, "%d: waiting after error report\n", (int)getpid());
568 die ("unknown %d", stop
);
573 int main (int argc
, char **argv
)
576 SaSelectionObjectT select_fd
;
580 select_fd
= comp_init();
584 tv
.tv_sec
= 2; /* related to value in amf.conf! */
586 FD_SET (select_fd
, &read_fds
);
587 result
= select (select_fd
+ 1, &read_fds
, 0, 0, &tv
);
589 if (errno
== EINTR
) {
592 die ("select failed - %s", strerror (errno
));
594 } else if (result
> 0) {
596 result
= saAmfDispatch (handle
, SA_DISPATCH_ALL
);
597 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
598 fprintf(stderr
, "%d: TRY_AGAIN received\n", (int)getpid());
601 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
603 if (result
!= SA_AIS_OK
) {
604 die ("saAmfDispatch failed %d", result
);
609 result
= saAmfHealthcheckConfirm (handle
, &compNameGlobal
,
610 &keyCompInvoked
, SA_AIS_OK
);
611 if (result
== SA_AIS_ERR_TRY_AGAIN
) {
612 fprintf(stderr
, "%d: TRY_AGAIN received\n", (int)getpid());
615 } while (result
== SA_AIS_ERR_TRY_AGAIN
);
617 if (result
!= SA_AIS_OK
) {
618 die ("saAmfHealthcheckConfirm failed %d", result
);
623 fprintf(stderr
, "%d: exiting...\n", (int)getpid());