Skip Navigation Links
Exit Print View
| Oracle Solaris Cluster Data Services Developer's Guide Oracle Solaris Cluster 4.1

Search Scope:

- This Document
- Entire Library

## `xfnts_start` Method

The RGM runs the `Start` method on a cluster node when the resource group that contains the data service resource is brought online on that node or when the resource is enabled. In the `ORCL.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 the PMF. The 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 housekeeping functions. `scds_initialize()` Function and the `scds_initialize`(3HA) man page contain more information.

### Validating the Service Before Starting the X Font Server

Before the `xfnts_start` method attempts to start the X Font Server, it calls `svc_validate()` to verify that a correct configuration is in place to support the `xfs` daemon.

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

See `xfnts_validate` Method for details.

### Starting the Service With `svc_start()`

The `xfnts_start` method calls the `svc_start()` method, which is defined in the `xfnts.c` file, to start the `xfs` daemon. This section describes `svc_start()`.

The command to start 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. The cluster administrator provides specific values for these properties when he or she configures the data service.

The `xfnts_start` method declares these properties as string arrays. The `xfnts_start` method obtains the values that the cluster administrator sets by using the `scds_get_ext_confdir_list()` and `scds_get_port_list()` functions. These functions are described in the `scds_property_functions`(3HA) man page.

    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) {
          scds_syslog(LOG_ERR,
              "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`.

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

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

The `xfnts_start` method passes the `xfs` command line to `scds_pmf_start()` to start the data service under the control of the PMF.

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

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

Note the following points about the call to `scds_pmf_start()`:

- The `SCDS_PMF_TYPE_SVC` argument identifies the program to start as a data service application. This method can also start a fault monitor or some other type of application.

- The `SCDS_PMF_SINGLE_INSTANCE` argument identifies this as a single-instance resource.

- The `cmd` argument is the command line that was generated previously.

- The final argument, `-1`, specifies the child monitoring level. The `-1` value specifies that the PMF monitor all children as well as the original process.

Before returning, `svc_pmf_start()` frees the memory that is allocated for the `portlist` structure.

    scds_free_port_list(portlist);
    return (err);

### Returning From `svc_start()`

Even when `svc_start()` returns successfully, the underlying application might have 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. The `svc_start()` method calls `svc_wait()`, which is defined in the `xfnts.c` file, to verify that the application is running.

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

       rc = svc_wait(scds_handle);

       scds_syslog_debug(DBG_LEVEL_HIGH,
           "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()` function calls `scds_get_netaddr_list()` to obtain the network address resources that are needed to probe the application.

    /* obtain the network resource to use for probing */
       if (scds_get_netaddr_list(scds_handle, &netaddr)) {
          scds_syslog(LOG_ERR,
              "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) {
          scds_syslog(LOG_ERR,
              "No network address resource in resource group.");
          return (1);
       }

The `svc_wait()` function obtains the `Start_timeout` and `Stop_timeout` values.

    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, `svc_wait()` calls `scds_svc_wait()` and passes a timeout value equivalent to three percent of the `Start_timeout` value. The `svc_wait()` function calls the `svc_probe()` function to verify that the application has started. The `svc_probe()` method makes a simple socket connection to the server on the specified port. If it fails to connect to the port, `svc_probe()` returns a value of 100, which indicates a total failure. If the connect goes through but the disconnect to the port fails, `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 that is specified by the `Retry_interval` property of the resource, the `scds_svc_wait()` function returns failure. In this case, the `svc_start()` function also returns failure.

    #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].hostname,
              netaddr->netaddrs[0].port_proto.port, probe_timeout);
          if (rc == SCHA_ERR_NOERR) {
             /* Success. Free up resources and return */
             scds_free_netaddr_list(netaddr);
             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 that are allocated by `scds_initialize()`. `scds_initialize()` Function and the `scds_close`(3HA) man page contain more information.

Copyright © 2000, 2012, Oracle and/or its affiliates. All rights reserved. Legal Notices |