Sun Cluster 3.1 Data Services Developer's Guide

The xfnts_start Method

The RGM invokes the Start method on a cluster node when the resource group containing the data service resource is brought online on that node or when the resource is enabled. In the SUNW.xfnts sample resource type, the xfnts_start method activates the xfs daemon on that node.

The xfnts_start method calls scds_pmf_start to start the daemon under PMF. PMF provides automatic failure notification and restart features, as well as integration with the fault monitor.

Note –

The first call in xfnts_start is to scds_initialize, which performs some necessary house-keeping functions (see The scds_initialize Call and the scds_initialize(3HA) man page for details).

Validating the Service Before Starting

Before it attempts to start the X Font Server, the xfnts_start method calls svc_validate to verify that a proper configuration is in place to support the xfs daemon (see The xfnts_validate Method for details), as follows.

Example 8–3

rc = svc_validate(scds_handle);
   if (rc != 0) {
          "Failed to validate configuration.");
      return (rc);

Starting the Service

The xfnts_start method calls the svc_start method, defined in xfnts.c to start the xfs daemon. This section describes svc_start.

The command to launch the xfs daemon is as follows.

xfs -config config_directory/fontserver.cfg -port port_number

The Confdir_list extension property identifies the config_directory while the Port_list system property identifies the port_number. When the cluster administrator configures the data service, he provides specific values for these properties.

The xfnts_start method declares these properties as string arrays and obtains the values the administrator sets using the scds_get_ext_confdir_list(3HA) and scds_get_port_list(3HA) functions, as follows.

Example 8–4

scha_str_array_t *confdirs;
scds_port_list_t    *portlist;
scha_err_t   err;

   /* get the configuration directory from the confdir_list property */
   confdirs = scds_get_ext_confdir_list(scds_handle);

   (void) sprintf(xfnts_conf, "%s/fontserver.cfg", confdirs->str_array[0]);

   /* obtain the port to be used by XFS from the Port_list property */
   err = scds_get_port_list(scds_handle, &portlist);
   if (err != SCHA_ERR_NOERR) {
          "Could not access property Port_list.");
      return (1);

Note that the confdirs variable points to the first element (0) of the array.

The xfnts_start method uses sprintf to form the command line for xfs as follows.

Example 8–5

/* Construct the command to start the xfs daemon. */
   (void) sprintf(cmd,
       "/usr/openwin/bin/xfs -config %s -port %d 2>/dev/null",
       xfnts_conf, portlist->ports[0].port);

Note that he output is redirected to dev/null to suppress messages generated by the daemon.

The xfnts_start method passes the xfs command line to scds_pmf_start to start the data service under control of PMF, as follows.

Example 8–6

scds_syslog(LOG_INFO, "Issuing a start request.");
   err = scds_pmf_start(scds_handle, SCDS_PMF_TYPE_SVC,

   if (err == SCHA_ERR_NOERR) {
          "Start command completed successfully.");
   } else {
          "Failed to start HA-XFS ");

Note the following about the call to scds_pmf_start.

Before returning, svc_pmf_start frees the memory allocated for the portlist structure, as follows.

return (err);

Returning From svc_start

Even when svc_start returns successfully, it is possible the underlying application failed to start. Therefore, svc_start must probe the application to verify that it is running before returning a success message. The probe must also take into account that the application might not be immediately available because it takes some time to start up. The svc_start method calls svc_wait, which is defined in xfnts.c, to verify the application is running, as follows.

Example 8–7

/* Wait for the service to start up fully */
       "Calling svc_wait to verify that service has started.");

   rc = svc_wait(scds_handle);

       "Returned from svc_wait");

   if (rc == 0) {
      scds_syslog(LOG_INFO, "Successfully started the service.");
   } else {
      scds_syslog(LOG_ERR, "Failed to start the service.");

The svc_wait method calls scds_get_netaddr_list(3HA) to obtain the network-address resources needed to probe the application, as follows.

Example 8–8

/* obtain the network resource to use for probing */
   if (scds_get_netaddr_list(scds_handle, &netaddr)) {
          "No network address resources found in resource group.");
      return (1);

   /* Return an error if there are no network resources */
   if (netaddr == NULL || netaddr->num_netaddrs == 0) {
          "No network address resource in resource group.");
      return (1);

Then svc_wait obtains the start_timeout and stop_timeout values, as follows.

Example 8–9

svc_start_timeout = scds_get_rs_start_timeout(scds_handle)
   probe_timeout = scds_get_ext_probe_timeout(scds_handle)

To account for the time the server might take to start up, svc_wait calls scds_svc_wait and passes a timeout value equivalent to three percent of the start_timeout value. Then svc_wait calls svc_probe to verify that the application has started. The svc_probe method makes a simple socket connection to the server on the specified port. If fails to connect to the port, svc_probe returns a value of 100, indicating total failure. If the connection goes through but the disconnect to the port fails, then svc_probe returns a value of 50.

On failure or partial failure of svc_probe, svc_wait calls scds_svc_wait with a timeout value of 5. The scds_svc_wait method limits the frequency of the probes to every five seconds. This method also counts the number of attempts to start the service. If the number of attempts exceeds the value of the Retry_count property of the resource within the period specified by the Retry_interval property of the resource, the scds_svc_wait method returns failure. In this case, the svc_start method also returns failure.

Example 8–10

#define    SVC_CONNECT_TIMEOUT_PCT    95
#define    SVC_WAIT_PCT       3
   if (scds_svc_wait(scds_handle, (svc_start_timeout * SVC_WAIT_PCT)/100)
      != SCHA_ERR_NOERR) {

      scds_syslog(LOG_ERR, "Service failed to start.");
      return (1);

   do {
       * probe the data service on the IP address of the
       * network resource and the portname
      rc = svc_probe(scds_handle,
          netaddr->netaddrs[0].port_proto.port, probe_timeout);
      if (rc == SCHA_ERR_NOERR) {
         /* Success. Free up resources and return */
         return (0);

       /* Call scds_svc_wait() so that if service fails too
      if (scds_svc_wait(scds_handle, SVC_WAIT_TIME)
         != SCHA_ERR_NOERR) {
         scds_syslog(LOG_ERR, "Service failed to start.");
         return (1);

   /* Rely on RGM to timeout and terminate the program */
   } while (1);

Note –

Before it exits, the xfnts_start method calls scds_close to reclaim resources allocated by scds_initialize. See The scds_initialize Call and the scds_close(3HA) man page for details.