root/usr/src/cmd/rcap/common/rcapd_conf.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <strings.h>
#include <fcntl.h>
#include <unistd.h>
#include <libscf.h>
#include <libscf_priv.h>
#include <libuutil.h>
#include "rcapd.h"
#include "rcapd_conf.h"
#include "rcapd_stat.h"
#include "utils.h"

/*
 * Read configuration and set the fields of an rcfg_t correspondingly.
 * Verify that the statistics file is writable, with the optional
 * verify_stat_file_creation() callback.
 */
int
rcfg_read(rcfg_t *_rcfg, int(*verify_stat_file_creation)(void))
{
        scf_simple_handle_t     *simple_h;
        uint64_t                count_val;
        int                     ret = E_ERROR;

        rcfg_init(_rcfg);

        if ((simple_h = scf_general_pg_setup(RCAP_FMRI, CONFIG_PG))
            == NULL) {
                warn(gettext("SMF initialization problem: %s\n"),
                    scf_strerror(scf_error()));
                goto err;
        }

        if (scf_read_count_property(simple_h, PRESSURE, &count_val)
            == SCF_FAILED) {
                warn(gettext("Configuration property '%s' "
                    "not found. \n"), PRESSURE);
                goto err;
        } else {
                if (count_val > 100)
                        _rcfg->rcfg_memory_cap_enforcement_pressure = 100;
                else
                        _rcfg->rcfg_memory_cap_enforcement_pressure
                            = count_val;

                debug("cap max pressure: %d%%\n",
                    _rcfg->rcfg_memory_cap_enforcement_pressure);
        }

        if (scf_read_count_property(simple_h, RECONFIG_INT, &count_val)
            == SCF_FAILED) {
                warn(gettext("Configuration property '%s' "
                    "not found. \n"), RECONFIG_INT);
                goto err;
        } else {
                _rcfg->rcfg_reconfiguration_interval = count_val;
                debug("reconfiguration interval: %d seconds\n",
                    _rcfg->rcfg_reconfiguration_interval);
        }

        if (scf_read_count_property(simple_h, REPORT_INT, &count_val)
            == SCF_FAILED) {
                warn(gettext("Configuration property '%s' "
                    "not found. \n"), REPORT_INT);
                goto err;
        } else {
                _rcfg->rcfg_report_interval = count_val;
                debug("report interval: %d seconds\n",
                    _rcfg->rcfg_report_interval);
        }

        if (scf_read_count_property(simple_h, RSS_SAMPLE_INT, &count_val)
            == SCF_FAILED) {
                warn(gettext("Configuration property '%s' "
                    "not found. \n"), RSS_SAMPLE_INT);
                goto err;
        } else {
                _rcfg->rcfg_rss_sample_interval = count_val;
                debug("RSS sample interval: %d seconds\n",
                    _rcfg->rcfg_rss_sample_interval);
        }

        if (scf_read_count_property(simple_h, WALK_INT, &count_val)
            == SCF_FAILED) {
                warn(gettext("Configuration property '%s' "
                    "not found. \n"), WALK_INT);
                goto err;
        } else {
                _rcfg->rcfg_proc_walk_interval = count_val;
                debug("proc_walk interval: %d seconds\n",
                    _rcfg->rcfg_proc_walk_interval);
        }

        if (_rcfg->rcfg_mode_name == NULL) {
                /*
                 * Set project mode, by default.
                 */
                _rcfg->rcfg_mode = rctype_project;
                _rcfg->rcfg_mode_name = "project";
                debug("mode: %s\n", _rcfg->rcfg_mode_name);
        }

        if (verify_stat_file_creation != 0 && verify_stat_file_creation()
            != 0) {
                warn(gettext("cannot create statistics file, " "%s"),
                    _rcfg->rcfg_stat_file);
                goto err;
        }

        debug("done parsing\n");
        ret = E_SUCCESS;
        goto out;

err:
        if (scf_error() != SCF_ERROR_NONE) {
                warn(gettext("Unexpected libscf error: %s. \n"),
                    scf_strerror(scf_error()));
        }

out:
        scf_simple_handle_destroy(simple_h);
        return (ret);
}

void
rcfg_init(rcfg_t *rcfg)
{
        bzero(rcfg, sizeof (*rcfg));
        (void) strcpy(rcfg->rcfg_stat_file, STAT_FILE_DEFAULT);
}

/*
 * Modify configuration in repository given the rcfg_t structure.
 */
int
modify_config(rcfg_t *conf)
{
        scf_simple_handle_t     *simple_h;
        scf_transaction_t       *tx = NULL;
        int                     rval, ret = E_ERROR;

        if ((simple_h = scf_general_pg_setup(RCAP_FMRI, CONFIG_PG))
            == NULL) {
                warn(gettext("SMF initialization problem: %s\n"),
                    scf_strerror(scf_error()));
                goto out;
        }

        if ((tx = scf_transaction_setup(simple_h)) == NULL) {
                warn(gettext("SMF initialization problem: %s\n"),
                    scf_strerror(scf_error()));
                goto out;
        }

        do {
                if (scf_set_count_property(tx, PRESSURE,
                    conf->rcfg_memory_cap_enforcement_pressure, 0)
                    != SCF_SUCCESS) {
                        warn(gettext("Couldn't set '%s' property. \n"),
                            PRESSURE);
                        goto out;
                }

                if (scf_set_count_property(tx, RECONFIG_INT,
                    conf->rcfg_reconfiguration_interval, 0) != SCF_SUCCESS) {
                        warn(gettext("Couldn't set '%s' property. \n"),
                            RECONFIG_INT);
                        goto out;
                }

                if (scf_set_count_property(tx, RSS_SAMPLE_INT,
                    conf->rcfg_rss_sample_interval, 0) != SCF_SUCCESS) {
                        warn(gettext("Couldn't set '%s' property. \n"),
                            RSS_SAMPLE_INT);
                        goto out;
                }

                if (scf_set_count_property(tx, REPORT_INT,
                    conf->rcfg_report_interval, 0) != SCF_SUCCESS) {
                        warn(gettext("Couldn't set '%s' property. \n"),
                            REPORT_INT);
                        goto out;
                }

                if (scf_set_count_property(tx, WALK_INT,
                    conf->rcfg_proc_walk_interval, 0) != SCF_SUCCESS) {
                        warn(gettext("Couldn't set '%s' property. \n"),
                            WALK_INT);
                        goto out;
                }

                if ((rval = scf_transaction_commit(tx)) == -1)
                        goto out;

                if (rval == 0) {
                        if (scf_transaction_restart(simple_h, tx)
                            != SCF_SUCCESS) {
                                warn(gettext("SMF initialization problem: "
                                    "%s\n"), scf_strerror(scf_error()));
                                goto out;
                        }
                }
        } while (rval == 0);

        ret = E_SUCCESS;

out:
        if (tx != NULL) {
                scf_transaction_destroy_children(tx);
                scf_transaction_destroy(tx);
        }
        scf_simple_handle_destroy(simple_h);
        return (ret);
}