diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/pools | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/pools')
129 files changed, 24137 insertions, 0 deletions
diff --git a/usr/src/cmd/pools/Makefile b/usr/src/cmd/pools/Makefile new file mode 100644 index 0000000000..a26d82631f --- /dev/null +++ b/usr/src/cmd/pools/Makefile @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/Makefile +# + +include ../Makefile.cmd + +SUBDIRS= pooladm poolbind poolcfg poolstat poold + +all := TARGET = all +install := TARGET = install +clean := TARGET = clean +clobber := TARGET = clobber +lint := TARGET = lint +_msg := TARGET = _msg + +.KEEP_STATE: + +all install lint clean clobber _msg: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(MFLAGS) $(TARGET) + +FRC: diff --git a/usr/src/cmd/pools/Makefile.pools b/usr/src/cmd/pools/Makefile.pools new file mode 100644 index 0000000000..9b8f96eb1e --- /dev/null +++ b/usr/src/cmd/pools/Makefile.pools @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/Makefile.pools + +POOLSSRC = $(SRC)/cmd/pools +POOLSCOMMONDIR = $(POOLSSRC)/common + +COMMON_OBJS = utils.o +COMMON_SRCS = $(COMMON_OBJS:%.o=$(POOLSCOMMONDIR)/%.c) diff --git a/usr/src/cmd/pools/common/utils.c b/usr/src/cmd/pools/common/utils.c new file mode 100644 index 0000000000..7318688908 --- /dev/null +++ b/usr/src/cmd/pools/common/utils.c @@ -0,0 +1,114 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libintl.h> +#include <limits.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <errno.h> + +#include <pool.h> +#include "utils.h" + +static const char PNAME_FMT[] = "%s: "; +static const char ERRNO_FMT[] = ": %s\n"; + +static const char *pname; + +/*LINTLIBRARY*/ +const char * +get_errstr_err(int errnum, int syserr) +{ + const char *errstr; + + if (errnum == POE_SYSTEM) + errstr = strerror(syserr); + else + errstr = pool_strerror(errnum); + return (errstr); +} + +const char * +get_errstr(void) +{ + return (get_errstr_err(pool_error(), errno)); +} + +/*PRINTFLIKE1*/ +void +warn(const char *format, ...) +{ + int err = errno; + va_list alist; + + if (pname != NULL) + (void) fprintf(stderr, PNAME_FMT, pname); + + va_start(alist, format); + (void) vfprintf(stderr, format, alist); + va_end(alist); + + if (strrchr(format, '\n') == NULL) + (void) fprintf(stderr, ERRNO_FMT, strerror(err)); +} + +/*PRINTFLIKE1*/ +void +die(const char *format, ...) +{ + int err = errno; + va_list alist; + + if (pname != NULL) + (void) fprintf(stderr, PNAME_FMT, pname); + + va_start(alist, format); + (void) vfprintf(stderr, format, alist); + va_end(alist); + + if (strrchr(format, '\n') == NULL) + (void) fprintf(stderr, ERRNO_FMT, strerror(err)); + + exit(E_ERROR); +} + +const char * +getpname(const char *arg0) +{ + const char *p = strrchr(arg0, '/'); + + if (p == NULL) + p = arg0; + else + p++; + + pname = p; + return (p); +} diff --git a/usr/src/cmd/pools/common/utils.h b/usr/src/cmd/pools/common/utils.h new file mode 100644 index 0000000000..929e6c8eaa --- /dev/null +++ b/usr/src/cmd/pools/common/utils.h @@ -0,0 +1,109 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _UTILS_H +#define _UTILS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Error messages for pool commands */ +#define ERR_SET_TERM "cleanup installation failed: %s\n" +#define ERR_CONF_LOAD "cannot load configuration from %s: %s\n" +#define ERR_CMD_FILE_INIT "cannot initialise command sequence: %s\n" +#define ERR_PROP_TO_LIST "cannot add property %s to property list\n" +#define ERR_UNKNOWN_ENTITY "unrecognised entity %lld\n" +#define ERR_ASSOC_TO_LIST "cannot add association %s to association " \ + "list\n" +#define ERR_GET_ELEMENT_DETAILS "cannot get the %s details for %s: %s\n" +#define ERR_LOCATE_ELEMENT "cannot locate the %s, %s: %s\n" +#define ERR_CREATE_ELEMENT "cannot create the %s, %s: %s\n" +#define ERR_DESTROY_ELEMENT "cannot destroy the %s, %s: %s\n" +#define ERR_ALLOC_ELEMENT "cannot allocate %s: %s\n" +#define ERR_PUT_PROPERTY "put property %s failed: %s\n" +#define ERR_REMOVE_PROPERTY "remove property %s failed: %s\n" +#define ERR_GET_PROPERTY "get property %s failed: %s\n" +#define ERR_UNKNOWN_RESOURCE "unrecognized resource type: %d\n" +#define ERR_ASSOC_RESOURCE "cannot associate resource %s to pool: %s\n" +#define ERR_VALIDATION_FAILED "configuration failed strict validation: %s\n" +#define ERR_CONFIG_OPEN_FAILED "cannot open the configuration: %s\n" +#define ERR_CONFIG_SAVE_FAILED "cannot save the configuration: %s\n" +#define ERR_WRONG_SYSTEM_NAME "incorrect system name supplied: %s\n" +#define ERR_CMD_LINE_ALLOC "cannot create command, not enough memory\n" +#define ERR_PROP_ALLOC "cannot create property, not enough memory\n" +#define ERR_ASSOC_ALLOC "cannot create association, not enough memory\n" + +#define ERR_DISABLE "cannot disable pools" +#define ERR_ENABLE "cannot enable pools" +#define ERR_NOMEM "not enough memory\n" +#define ERR_PERMISSIONS "insufficient privileges\n" +#define ERR_PRIVILEGE "cannot access %s privileges" +#define ERR_OPEN_DYNAMIC "couldn't open pools state file: %s\n" +#define ERR_OPEN_STATIC "couldn't open configuration at '%s': %s\n" +#define ERR_VALIDATE_RUNTIME "configuration at '%s' cannot be instantiated "\ + "on current system\n" +#define ERR_COMMIT_DYNAMIC "couldn't commit configuration changes at '%s'"\ + ": %s\n" +#define ERR_REMOVE_DYNAMIC "couldn't remove dynamic configuration: %s\n" +#define ERR_COMMIT_STATIC "couldn't commit configuration changes at '%s'"\ + ": %s\n" +#define ERR_EXPORT_DYNAMIC "couldn't export pools state file to '%s': %s\n" +#define ERR_NO_POOLS "no pools defined\n" +#define ERR_XFER_COMPONENT "cannot transfer %s %s to %s: %s\n" +#define ERR_XFER_QUANTITY "cannot transfer %llu from %s to %s: %s\n" +#define ERR_CMDPARSE_FAILED "command parsing failed, terminating...\n" + +#define CONFIGURATION "configuration" +#define RESOURCE "resource" +#define POOL "pool" +#define PSET "pset" +#define COMPONENT "component" +#define CPU "cpu" +#define SYSTEM_NAME "system.name" +#define POOL_NAME "pool.name" +#define PSET_NAME "pset.name" +#define CPU_SYSID "cpu.sys_id" + +#define E_PO_SUCCESS 0 /* Exit status for success */ +#define E_ERROR 1 /* Exit status for error */ +#define E_USAGE 2 /* Exit status for usage error */ + +extern const char *get_errstr(void); +extern const char *get_errstr_err(int, int); +extern void warn(const char *, ...); +extern void die(const char *, ...); +extern const char *getpname(const char *); + +#ifdef __cplusplus +} +#endif + +#endif /* _UTILS_H */ diff --git a/usr/src/cmd/pools/pooladm/Makefile b/usr/src/cmd/pools/pooladm/Makefile new file mode 100644 index 0000000000..00fee62fd2 --- /dev/null +++ b/usr/src/cmd/pools/pooladm/Makefile @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/pooladm/Makefile + +PROG = pooladm +OBJS = pooladm.o +SRCS = $(OBJS:%.o=%.c) $(COMMON_SRCS) +POFILES = $(OBJS:.o=.po) + +include ../../Makefile.cmd +include ../Makefile.pools + +CFLAGS += -I$(POOLSCOMMONDIR) +LDLIBS += -lpool +XGETFLAGS = -a +CLOBBERFILES += $(POFILES) + +lint := LINTFLAGS += -I$(POOLSCOMMONDIR) + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) $(COMMON_OBJS) + $(LINK.c) -o $@ $(OBJS) $(COMMON_OBJS) $(LDLIBS) + $(POST_PROCESS) + +%.o : $(POOLSCOMMONDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +install: all $(ROOTUSRSBINPROG) + +clean: + $(RM) $(OBJS) $(COMMON_OBJS) $(POFILES) + +lint: lint_SRCS + +include ../../Makefile.targ diff --git a/usr/src/cmd/pools/pooladm/pooladm.c b/usr/src/cmd/pools/pooladm/pooladm.c new file mode 100644 index 0000000000..f2469ed189 --- /dev/null +++ b/usr/src/cmd/pools/pooladm/pooladm.c @@ -0,0 +1,258 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * pooladm - set, remove, or display active pool configurations. + */ + +#include <sys/zone.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <libintl.h> +#include <locale.h> +#include <string.h> +#include <priv.h> +#include <errno.h> +#include <zone.h> +#include <pool.h> +#include <unistd.h> +#include "utils.h" + +#ifndef TEXT_DOMAIN +#define TEXT_DOMAIN "SYS_TEST" +#endif + +static int Cflag; +static int Sflag; +static int Dflag; +static int Eflag; +static int Nflag; +static int Xflag; + +static void +usage(void) +{ + (void) fprintf(stderr, + gettext("Usage:\tpooladm [-n] [-s] [-c] [filename]\n")); + (void) fprintf(stderr, + gettext("Usage:\tpooladm [-n] -x\n")); + (void) fprintf(stderr, + gettext("Usage:\tpooladm -d | -e\n")); + exit(E_USAGE); +} + +static void +config_print(pool_conf_t *conf) +{ + char *buf; + pool_value_t *pv; + const char *tgt; + + if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) + != PO_SUCCESS) + die(gettext(ERR_OPEN_DYNAMIC), get_errstr()); + + if ((pv = pool_value_alloc()) == NULL || + pool_get_property(conf, pool_conf_to_elem(conf), "system.name", + pv) == POC_INVAL || + pool_value_get_string(pv, &tgt) != PO_SUCCESS) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + + if ((buf = pool_conf_info(conf, PO_TRUE)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), + tgt, get_errstr()); + pool_value_free(pv); + (void) printf("%s", buf); + free(buf); + (void) pool_conf_close(conf); +} + +static void +config_destroy(pool_conf_t *conf) +{ + if (pool_conf_open(conf, pool_dynamic_location(), PO_RDWR) + != PO_SUCCESS) + die(gettext(ERR_OPEN_DYNAMIC), get_errstr()); + if (pool_conf_remove(conf) != PO_SUCCESS) + die(gettext(ERR_REMOVE_DYNAMIC), get_errstr()); +} + +static void +config_commit(pool_conf_t *conf, const char *static_conf_name) +{ + if (pool_conf_open(conf, static_conf_name, Nflag || !Sflag ? + PO_RDONLY : PO_RDWR) != PO_SUCCESS) + die(gettext(ERR_OPEN_STATIC), static_conf_name, get_errstr()); + + if (pool_conf_validate(conf, POV_RUNTIME) != PO_SUCCESS) + die(gettext(ERR_VALIDATE_RUNTIME), static_conf_name); + if (!Nflag) { + if (pool_conf_commit(conf, PO_TRUE) != PO_SUCCESS) + die(gettext(ERR_COMMIT_DYNAMIC), static_conf_name, + get_errstr()); + /* + * Dump the updated state to the specified location + */ + if (Sflag) { + if (pool_conf_commit(conf, PO_FALSE) != PO_SUCCESS) + die(gettext(ERR_COMMIT_STATIC), + static_conf_name, get_errstr()); + } + } + (void) pool_conf_close(conf); +} + +int +main(int argc, char *argv[]) +{ + char c; + pool_conf_t *conf = NULL; + const char *static_conf_loc; + + (void) getpname(argv[0]); + (void) setlocale(LC_ALL, ""); + (void) textdomain(TEXT_DOMAIN); + + + while ((c = getopt(argc, argv, "cdensx")) != EOF) { + switch (c) { + case 'c': /* Create (or modify) system configuration */ + Cflag++; + break; + case 'd': /* Disable the pools facility */ + Dflag++; + break; + case 'e': /* Enable the pools facility */ + Eflag++; + break; + case 'n': /* Don't actually do anything */ + Nflag++; + break; + case 's': /* Update the submitted configuration */ + Sflag++; + break; + case 'x': /* Delete current system configuration */ + Xflag++; + break; + case '?': + default: + usage(); + /*NOTREACHED*/ + } + } + + /* + * Not all flags can be used at the same time. + */ + if ((Cflag || Sflag || Dflag || Eflag) && Xflag) + usage(); + + if ((Dflag || Eflag) && (Cflag || Sflag || Xflag)) + usage(); + + if (Dflag && Eflag) + usage(); + + argc -= optind; + argv += optind; + + if (! (Cflag || Sflag)) { + if (argc != 0) + usage(); + } else { + if (argc == 0) + static_conf_loc = pool_static_location(); + else if (argc == 1) + static_conf_loc = argv[0]; + else + usage(); + } + + if (!Nflag && (Cflag + Dflag + Eflag + Xflag != 0) && + !priv_ineffect(PRIV_SYS_RES_CONFIG)) + die(gettext(ERR_PERMISSIONS)); + + if (Dflag) { + if (pool_set_status(POOL_DISABLED) != PO_SUCCESS) + die(gettext(ERR_DISABLE)); + } else if (Eflag) { + if (pool_set_status(POOL_ENABLED) != PO_SUCCESS) { + if (errno == EEXIST) + die(gettext(ERR_ENABLE + ": System has active processor sets\n")); + else + die(gettext(ERR_ENABLE)); + } + } else { + if ((conf = pool_conf_alloc()) == NULL) + die(gettext(ERR_NOMEM)); + + if (Cflag + Sflag + Xflag == 0) { + /* + * No flags means print current system configuration + */ + config_print(conf); + } else if (!Nflag && Xflag) { + /* + * Destroy active pools configuration and + * remove the state file. + */ + config_destroy(conf); + } else { + /* + * Commit a new configuration. + */ + if (Cflag) + config_commit(conf, static_conf_loc); + else { + /* + * Dump the dynamic state to the + * specified location + */ + if (!Nflag && Sflag) { + if (pool_conf_open(conf, + pool_dynamic_location(), PO_RDONLY) + != PO_SUCCESS) + die(gettext(ERR_OPEN_DYNAMIC), + get_errstr()); + if (pool_conf_export(conf, + static_conf_loc, POX_NATIVE) != + PO_SUCCESS) + die(gettext(ERR_EXPORT_DYNAMIC), + static_conf_loc, get_errstr()); + (void) pool_conf_close(conf); + } + } + } + pool_conf_free(conf); + } + return (E_PO_SUCCESS); +} diff --git a/usr/src/cmd/pools/poolbind/Makefile b/usr/src/cmd/pools/poolbind/Makefile new file mode 100644 index 0000000000..9c0cdbdb2e --- /dev/null +++ b/usr/src/cmd/pools/poolbind/Makefile @@ -0,0 +1,64 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poolbind/Makefile + +PROG = poolbind +OBJS = poolbind.o +SRCS = $(OBJS:%.o=%.c) $(COMMON_SRCS) +POFILES = $(OBJS:.o=.po) + +include ../../Makefile.cmd +include ../Makefile.pools + +CFLAGS += -I$(POOLSCOMMONDIR) +LDLIBS += -lpool -lproject +XGETFLAGS = -a +CLOBBERFILES += $(POFILES) + +lint := LINTFLAGS += -I$(POOLSCOMMONDIR) + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) $(COMMON_OBJS) + $(LINK.c) -o $@ $(OBJS) $(COMMON_OBJS) $(LDLIBS) + $(POST_PROCESS) + +%.o : $(POOLSCOMMONDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +install: all $(ROOTUSRSBINPROG) + +clean: + $(RM) $(OBJS) $(COMMON_OBJS) $(POFILES) + +lint: lint_SRCS + +include ../../Makefile.targ diff --git a/usr/src/cmd/pools/poolbind/poolbind.c b/usr/src/cmd/pools/poolbind/poolbind.c new file mode 100644 index 0000000000..395a09bbdf --- /dev/null +++ b/usr/src/cmd/pools/poolbind/poolbind.c @@ -0,0 +1,301 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * poolbind - bind processes, tasks, and projects to pools, and query process + * pool bindings + */ + +#include <libgen.h> +#include <pool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> + +#include <locale.h> +#include <libintl.h> + +#include <sys/procset.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <project.h> +#include <zone.h> + +#include "utils.h" + +#ifndef TEXT_DOMAIN +#define TEXT_DOMAIN "SYS_TEST" +#endif + +#define eFLAG 0x1 +#define iFLAG 0x2 +#define pFLAG 0x4 +#define qFLAG 0x8 +#define QFLAG 0x10 + +static const char OPTS[] = "Qei:p:q"; +static struct { + idtype_t idtype; + char *str; +} idtypes[] = { + { P_PID, "pid" }, + { P_TASKID, "taskid" }, + { P_PROJID, "projid" }, + { P_PROJID, "project" }, + { P_ZONEID, "zoneid" }, + { -1, NULL } +}; + +int error = E_PO_SUCCESS; + +void exec_cmd(char *, char *[]); +void process_ids(char *, uint_t, idtype_t, char *, int, char *[]); + +void +usage(void) +{ + (void) fprintf(stderr, + gettext("Usage:\n" + " poolbind -p pool_name -e command [arguments...]\n" + " poolbind -p pool_name " + "[-i pid | -i taskid | -i projid | -i zoneid] id ...\n" + " poolbind -q pid ...\n" + " poolbind -Q pid ... \n")); + exit(E_USAGE); +} + +int +print_resource_binding(const char *type, pid_t pid) +{ + char *resource_name; + + if ((resource_name = pool_get_resource_binding(type, pid)) == NULL) + warn(gettext("getting '%s' binding for %d: %s\n"), type, + (int)pid, get_errstr()); + else + (void) printf("%d\t%s\t%s\n", (int)pid, type, resource_name); + free(resource_name); + return (PO_SUCCESS); +} + +int +main(int argc, char *argv[]) +{ + char c; + int i; + idtype_t idtype = P_PID; + char *idstr = "pid"; + char *pool_name = NULL; + uint_t flags = 0; + int status; + + (void) getpname(argv[0]); + (void) setlocale(LC_ALL, ""); + (void) textdomain(TEXT_DOMAIN); + + while ((c = getopt(argc, argv, OPTS)) != EOF) { + switch (c) { + case 'Q': + if (flags & (qFLAG | iFLAG | pFLAG)) + usage(); + flags |= QFLAG; + break; + case 'e': + if (flags & (iFLAG | qFLAG | QFLAG)) + usage(); + flags |= eFLAG; + break; + case 'i': + for (i = 0; idtypes[i].str != NULL; i++) { + if (strcmp(optarg, idtypes[i].str) == 0) { + idtype = idtypes[i].idtype; + idstr = idtypes[i].str; + break; + } + } + if ((flags & (iFLAG | qFLAG | QFLAG)) || + idtypes[i].str == NULL) + usage(); + flags |= iFLAG; + break; + case 'p': + if (flags & (pFLAG | qFLAG | QFLAG)) + usage(); + flags |= pFLAG; + pool_name = optarg; + break; + case 'q': + if (flags & (pFLAG | iFLAG | QFLAG)) + usage(); + flags |= qFLAG; + break; + case '?': + default: + usage(); + } + } + + argc -= optind; + argv += optind; + + if (flags & eFLAG && pool_name == NULL) + usage(); + if (argc < 1 || (flags & (pFLAG | qFLAG | QFLAG)) == 0) + usage(); + + /* + * Check to see that the pools facility is enabled + */ + if (pool_get_status(&status) != PO_SUCCESS) + die((ERR_OPEN_DYNAMIC), get_errstr()); + if (status == POOL_DISABLED) + die((ERR_OPEN_DYNAMIC), strerror(ENOTACTIVE)); + + if (flags & eFLAG) + exec_cmd(pool_name, argv); + /*NOTREACHED*/ + else + process_ids(pool_name, flags, idtype, idstr, argc, argv); + + return (error); +} + +void +exec_cmd(char *pool_name, char *argv[]) +{ + if (pool_set_binding(pool_name, P_PID, getpid()) != PO_SUCCESS) { + warn(gettext("binding to pool '%s': %s\n"), pool_name, + get_errstr()); + error = E_ERROR; + return; + } + + if (execvp(basename(argv[0]), argv) == -1) + die(gettext("exec of %s failed"), argv[0]); + /*NOTREACHED*/ +} + +void +process_ids(char *pool_name, uint_t flags, idtype_t idtype, char *idstr, + int argc, char *argv[]) +{ + int i; + id_t id; + + for (i = 0; i < argc; i++) { + char *endp; + char *poolname; + + errno = 0; + id = (id_t)strtol(argv[i], &endp, 10); + if (errno != 0 || + (endp && endp != argv[i] + strlen(argv[i])) || + (idtype == P_ZONEID && + getzonenamebyid(id, NULL, 0) == -1)) { + /* + * The string does not completely parse to + * an integer, or it represents an invalid + * zone id. + */ + + /* + * It must be a project or zone name. + */ + if (idtype == P_ZONEID) { + if (zone_get_id(argv[i], &id) != 0) { + warn(gettext("invalid zone '%s'\n"), + argv[i]); + error = E_ERROR; + continue; + } + /* make sure the zone is booted */ + if (id == -1) { + warn(gettext("zone '%s' is not " + "active\n"), argv[i]); + error = E_ERROR; + continue; + } + } else if (idtype == P_PROJID) { + if ((id = getprojidbyname(argv[i])) < 0) { + warn(gettext("failed to get project " + "id for project: '%s'"), argv[i]); + error = E_ERROR; + continue; + } + } else { + warn(gettext("invalid %s '%s'\n"), + idstr, argv[i]); + error = E_ERROR; + continue; + } + } + + if (flags & pFLAG) { + if (pool_set_binding(pool_name, idtype, id) != + PO_SUCCESS) { + warn(gettext("binding %s %ld to pool '%s': " + "%s\n"), idstr, id, pool_name, + get_errstr()); + error = E_ERROR; + } + continue; + } + + if (flags & qFLAG) { + if ((poolname = pool_get_binding(id)) == NULL) { + warn(gettext("couldn't determine binding for " + "pid %ld: %s\n"), id, get_errstr()); + error = E_ERROR; + } else { + (void) printf("%ld\t%s\n", id, poolname); + free(poolname); + } + } + if (flags & QFLAG) { + uint_t j, count; + const char **resource_types; + (void) pool_resource_type_list(NULL, &count); + + if ((resource_types = malloc(count * + sizeof (const char *))) == NULL) { + warn(gettext("couldn't allocate query memory " + "for pid %ld: %s\n"), id, get_errstr()); + error = E_ERROR; + } + (void) pool_resource_type_list(resource_types, &count); + + for (j = 0; j < count; j++) + (void) print_resource_binding(resource_types[j], + (pid_t)id); + free(resource_types); + } + } +} diff --git a/usr/src/cmd/pools/poolcfg/Makefile b/usr/src/cmd/pools/poolcfg/Makefile new file mode 100644 index 0000000000..d7b35660b1 --- /dev/null +++ b/usr/src/cmd/pools/poolcfg/Makefile @@ -0,0 +1,81 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 (c) 2001 by Sun Microsystems, Inc. +# All rights reserved. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poolbind/Makefile + +PROG = poolcfg +OBJS = poolcfg_lex.o poolcfg_grammar.o +SRCS = $(OBJS:%.o=%.c) $(COMMON_SRCS) +POFILES = $(OBJS:.o=.po) +POFILE = poolcfg.po + +include ../../Makefile.cmd +include ../Makefile.pools + +LFLAGS = -t +YFLAGS = -d +CFLAGS += -I$(POOLSCOMMONDIR) +LDLIBS += -lpool -ll +XGETFLAGS = -a +CLOBBERFILES += poolcfg_lex.c poolcfg_grammar.c poolcfg_grammar.h + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) $(COMMON_OBJS) + $(LINK.c) -o $@ $(OBJS) $(COMMON_OBJS) $(LDLIBS) + $(POST_PROCESS) + +%.o : $(POOLSCOMMONDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +install: all $(ROOTUSRSBINPROG) + +poolcfg_lex.c: poolcfg.l poolcfg_grammar.h + $(LEX) $(LFLAGS) poolcfg.l > $@ + +poolcfg_grammar.h poolcfg_grammar.c: poolcfg.y + $(YACC) $(YFLAGS) poolcfg.y + @$(MV) y.tab.h poolcfg_grammar.h + @$(MV) y.tab.c poolcfg_grammar.c + +poolcfg_lex.o poolcfg_grammar.o := CCVERBOSE = + +clean: + $(RM) $(OBJS) $(COMMON_OBJS) $(POFILES) + +$(POFILE): $(POFILES) + $(RM) $@; cat $(POFILES) > $@ + +# +# We don't do lint of lex- and yacc- generated source files +# +lint: + +include ../../Makefile.targ diff --git a/usr/src/cmd/pools/poolcfg/poolcfg.h b/usr/src/cmd/pools/poolcfg/poolcfg.h new file mode 100644 index 0000000000..75aeca7286 --- /dev/null +++ b/usr/src/cmd/pools/poolcfg/poolcfg.h @@ -0,0 +1,79 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _POOLCFG_H +#define _POOLCFG_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + po_create, + po_remove +} prop_op_t; + +typedef union { + uint64_t u; + int64_t i; + double d; + uchar_t b; + const char *s; +} pv_u; + +typedef struct prop { + const char *prop_name; + pool_value_t *prop_value; + prop_op_t prop_op; + struct prop *prop_next; +} prop_t; + +typedef struct assoc { + int assoc_type; + const char *assoc_name; + struct assoc *assoc_next; +} assoc_t; + +typedef struct cmd { + void (*cmd)(struct cmd *); + const char *cmd_tgt1; + const char *cmd_tgt2; + uint64_t cmd_qty; + prop_t *cmd_prop_list; + assoc_t *cmd_assoc_list; +} cmd_t; + +typedef void (*cmdfunc)(cmd_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _POOLCFG_H */ diff --git a/usr/src/cmd/pools/poolcfg/poolcfg.l b/usr/src/cmd/pools/poolcfg/poolcfg.l new file mode 100644 index 0000000000..0837674c7e --- /dev/null +++ b/usr/src/cmd/pools/poolcfg/poolcfg.l @@ -0,0 +1,264 @@ +%{ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" +#pragma error_messages(off, E_STATEMENT_NOT_REACHED) + +/* + * poolcfg.l + * + * Overview + * poolcfg.l implements a lexer for the poolcfg(1) utility.The lexer uses + * the token definitions generated by YACC in the file poolcfg_Grammar.h. + * To make token recognition simpler, the lexer uses a separate state for + * each of the different data types supported by poolcfg(1). + * + * States + * Lex provides the ability to minimise conflict between qualifying regexps + * by providing states. A regexp that is qualified by a state will only be + * used when the state is entered (using the BEGIN <state> command). (The + * exception to this rule, is that rules defined in the default state are + * available in all states.) + * + * poolcfg.l makes use of type states, one for each of the poolcfg(1) + * supported data types: + * + * ISTATE => int64_t + * USTATE => uint64_t + * BSTATE => uchar_t + * SSTATE => const char * + * DSTATE => double + * + * and a further state, CPUSTATE, to indicate the difference between matching + * a valid "name" (i.e. id) for a cpu and a valid name for other components of + * libpool. + * + * When a token indicating a variable declaration is matched, the corresponding + * state is saved in the state variable. Once the assignment ('=') token is + * matched, the stored state is entered and the additional state specific + * matching regular expressions become available. Once a state specific + * token is matched, the default state is restored. + * + */ +#include <stdlib.h> +#include <sys/types.h> +#include <assert.h> +#include <string.h> +#include <errno.h> +#include <libintl.h> + +#include <pool.h> +#include "utils.h" +#include "poolcfg.h" +#include "poolcfg_grammar.h" + +static int lex_lineno = 1; /* line-number for error reporting */ +static int state = INITIAL; /* state to be used */ +extern void yyerror(char *s); +extern int dofile; /* are we processing a file? */ +%} + +%s ISTATE +%s USTATE +%s BSTATE +%s SSTATE +%s DSTATE +%s CPUSTATE + +%% + +\n lex_lineno++; + +[ \t]+ ; + +#.* ; + +info { return PCC_INFO; } + +create { return PCC_CREATE; } + +destroy { return PCC_DESTROY; } + +modify { return PCC_MODIFY; } + +associate { return PCC_ASSOC; } + +transfer { + BEGIN USTATE; + return PCC_TRANSFER; + } + +discover { return PCC_DISC; } + +rename { return PCC_RENAME; } + +to { return PCK_TO; } + +from { return PCK_FROM; } + +int { + state=ISTATE; + return PCT_INT; + } + +uint { + state=USTATE; + return PCT_UINT; + } + +boolean { + state=BSTATE; + return PCT_BOOLEAN; + } + +string { + state=SSTATE; + return PCT_STRING; + } + +float { + state=DSTATE; + return PCT_FLOAT; + } + +cpu { + BEGIN CPUSTATE; + return PCE_CPU; + } + +pset { return PCE_PSET; } + +pool { return PCE_POOL; } + +system { return PCE_SYSTEM; } + +\( { return PCK_OPENLST; } + +\) { return PCK_CLOSELST; } + += { + BEGIN state; + return PCK_ASSIGN; + } + +\; { return PCK_SEPLST; } + +~ { return PCK_UNDEF; } + +<ISTATE>-?[0-9]+ { + yylval.ival = strtoll(yytext, NULL, 0); + if (errno == EINVAL || errno == ERANGE) { + yyerror(gettext("Invalid value")); + exit(E_ERROR); + } + BEGIN INITIAL; + return PCV_VAL_INT; + } + +<USTATE>[0-9]+ { + yylval.uval = strtoull(yytext, NULL, 0); + if (errno == EINVAL || errno == ERANGE) { + yyerror(gettext("Invalid value")); + exit(E_ERROR); + } + BEGIN INITIAL; + return PCV_VAL_UINT; + } + + +<BSTATE>true|false { + if (strcmp(yytext, "true") == 0) + yylval.bval = 1; + else + yylval.bval = 0; + BEGIN INITIAL; + return PCV_VAL_BOOLEAN; + } + +<SSTATE>\"[^\"\n]*[\"\n] { + if((yylval.sval = strdup(yytext+1)) == NULL) { + yyerror(gettext("Out of memory")); + exit(E_ERROR); + } + if (yylval.sval[yyleng-2] =='"') + yylval.sval[yyleng-2] = 0; + BEGIN INITIAL; + return PCV_VAL_STRING; + } + +<DSTATE>([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { + yylval.dval = strtod(yytext, (char **)NULL); + if (errno == EINVAL || errno == ERANGE) { + yyerror(gettext("Invalid value")); + exit(E_ERROR); + } + BEGIN INITIAL; + return PCV_VAL_FLOAT; + } + +[A-Za-z][A-Za-z0-9,._-]* { + if ((yylval.sval = strdup(yytext)) == NULL) { + yyerror(gettext("Out of memory")); + exit(E_ERROR); + } + return PCV_SYMBOL; + } + +<CPUSTATE>[0-9]+ { + if ((yylval.sval = strdup(yytext)) == NULL) { + yyerror(gettext("Out of memory")); + exit(E_ERROR); + } + BEGIN INITIAL; + return PCV_SYMBOL; + } +. { + yyerror(gettext("Illegal character")); + exit(E_ERROR); + } + +%% + +void +yyerror(char *s) +{ + if (dofile == PO_TRUE) { + if (yytext[0] == '\0') { + (void) warn(gettext("line %d, %s, token expected\n"), + lex_lineno, s); + return; + } + (void) warn(gettext("line %d, %s at '%s'\n"), lex_lineno, s, + yytext); + } else { + if (yytext[0] == '\0') { + (void) warn(gettext("%s, token expected\n"), s); + return; + } + (void) warn(gettext("%s at '%s'\n"), s, yytext); + } +} + diff --git a/usr/src/cmd/pools/poolcfg/poolcfg.y b/usr/src/cmd/pools/poolcfg/poolcfg.y new file mode 100644 index 0000000000..3fdd526805 --- /dev/null +++ b/usr/src/cmd/pools/poolcfg/poolcfg.y @@ -0,0 +1,1596 @@ +%{ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Overview of poolcfg(1) + * + * poolcfg(1) implements a small grammar for manipulating pools configurations. + * yacc(1) is used to generate the parser and poolcfg.l contains a simple lexer + * (generted by lex(1)) to perform lexical processsing of the input. + * + * Refer to the poolcfg(1) manpage for more details of the grammar. + * + * The parser is designed so that all operations implement the same interface. + * This allows the parser to simply build up the command (using the cmd + * variable) by storing arguments and a pointer to the desired function in the + * cmd. The command is executed when the commands production is matched. + * + * Properties and associations are stored in simple linked lists and processed + * in the order submitted by the user. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <locale.h> +#include <libintl.h> +#include <sys/utsname.h> + +#include <pool.h> +#include "utils.h" +#include "poolcfg.h" + + + +#define USAGE1 \ +"Usage:\n" \ +"%s -h\n" \ +"%s -c command [ -d | [ file ] ]\n" \ +"%s -f command-file [-d | [ file ] ]\n\n" + +#define USAGE2 \ +"command:\n" \ +" info [entity name]\n" \ +" display configuration (or specified portion) in readable form\n" \ +" create entity name [property-list]\n" \ +" make an entity of the specified type and name\n" \ +" destroy entity name\n" \ +" remove the specified entity\n" \ +" modify entity name [property-list]\n" \ +" change the listed properties on the named entity\n" \ +" associate pool name [resource-list]\n" \ +" connect one or more resources to a pool, or replace one or more\n" \ +" existing connections\n" \ +" transfer to resource name [component-list]\n" \ +" transfer one or more discreet components to a resource\n" \ +" transfer [quantity] from resource src to tgt\n" \ +" transfer a resource quantity from src to tgt\n" \ +" transfer [quantity] to resource tgt from src\n" \ +" transfer a resource quantity to tgt from src\n" \ +" discover\n" \ +" create a system entity, with one pool entity and resources to\n" \ +" match current system configuration\n" \ +" rename entity old_name to new_name\n" \ +" change the name of the entity on the system to its new name\n\n" \ +"property-list:\n" \ +" ( proptype name = value [ ; proptype name = value ]* )\n" \ +" where multiple definitions in the sentence for a given\n" \ +" proptype, name pair are ignored; the last one provided is used.\n" \ +" For property deletion, use \"~ proptype name\"\n\n" \ +"resource-list:\n" \ +" ( resource name [; resource name ] )\n" \ +" where multiple uses of a resource are ignored; the last provided\n" \ +" is the one used.\n" \ +" There is no deletion syntax for resource lists.\n" \ +"component-list:\n" \ +" ( cpu id [; cpu id ] )\n" \ +" where multiple uses of the same component cause the last provided\n" \ +" to be the one used.\n" \ +" There is no deletion syntax for component lists.\n" \ +"entity:\n" \ +" system | pool | pset | cpu\n" \ +" where cpu is only valid for transfer, info and modify commands.\n" \ +"resource:\n" \ +" pset\n\n" \ +"proptype:\n" \ +" boolean | int | uint | string | float\n\n" + +int dofile = PO_FALSE; /* poolcfg.l uses this for errors */ +int conf_edit_error = POE_OK; /* cached error for error reporting */ +int conf_edit_errno = 0; /* cached errno for error reporting */ +int conf_list_error = POE_OK; /* cached error for error reporting */ +int conf_list_errno = 0; /* cached errno for error reporting */ +static const char cmdname[] = "poolcfg"; +static const char cmd_options[] = "c:df:h"; +static void usage(int); +static const char *max_suffix = ".max"; +static const char *min_suffix = ".min"; + +static const char *conf_file = NULL; /* Location of target config */ +static cmd_t *cmd = NULL; /* Command being processed */ +static pool_conf_t *conf = NULL; /* Config to be processed */ +static int edited = PO_FALSE; /* Has the configuration been changed */ + +/* yacc externals */ +extern FILE *yyin; +extern int yydebug; +extern void yyerror(char *s); + +/* Utility functions */ +static void arg_parse(const char *); +static void file_parse(const char *); +static cmd_t *alloc_cmd(void); +static prop_t *alloc_prop(prop_op_t); +static assoc_t *alloc_assoc(int, const char *); +static void free_cmd(cmd_t *); +static void check_conf_name(cmd_t *); +static void prop_list_walk(cmd_t *, pool_elem_t *); +static void assoc_list_walk(cmd_t *, pool_t *); +static void transfer_list_walk(cmd_t *, pool_resource_t *); +static void terminate(void); +static pool_component_t *get_cpu(const char *); +static void process_min_max(pool_resource_t *); + +/* Info Commands */ +static void parser_conf_info(cmd_t *); +static void parser_pool_info(cmd_t *); +static void parser_resource_info(cmd_t *, const char *); +static void parser_pset_info(cmd_t *); +static void parser_cpu_info(cmd_t *); + +/* Create Commands */ +static void parser_conf_create(cmd_t *); +static void parser_pool_create(cmd_t *); +static void parser_resource_create(cmd_t *, const char *); +static void parser_pset_create(cmd_t *); + +/* Destroy Commands */ +static void parser_conf_destroy(cmd_t *); +static void parser_pool_destroy(cmd_t *); +static void parser_resource_destroy(cmd_t *, const char *); +static void parser_pset_destroy(cmd_t *); + +/* Modify Commands */ +static void parser_conf_modify(cmd_t *); +static void parser_pool_modify(cmd_t *); +static void parser_resource_modify(cmd_t *, const char *); +static void parser_pset_modify(cmd_t *); +static void parser_cpu_modify(cmd_t *); + +/* Associate Commands */ +static void parser_pool_associate(cmd_t *); + +/* Assign Commands */ +static void parser_resource_xtransfer(cmd_t *); +static void parser_resource_transfer(cmd_t *); + +/* Discover Commands */ +static void parser_conf_discover(cmd_t *); + +/* Rename Commands */ +static void parser_rename(cmd_t *, pool_elem_t *, const char *); +static void parser_conf_rename(cmd_t *); +static void parser_pool_rename(cmd_t *); +static void parser_pset_rename(cmd_t *); + + +%} + +%union { + double dval; + uint64_t uval; + int64_t ival; + char *sval; + uchar_t bval; + cmd_t *cmd; + prop_t *prop; + pv_u val; + assoc_t *assoc; +} + +%start commands + +%token PCC_INFO PCC_CREATE PCC_DESTROY PCC_MODIFY PCC_ASSOC PCC_DISC PCC_RENAME +%token PCC_TRANSFER +%token PCK_FROM PCK_TO PCK_OPENLST PCK_CLOSELST PCK_SEPLST PCK_ASSIGN PCK_UNDEF +PCK_COMMAND +%token PCV_FILENAME PCV_SYMBOL PCV_VAL_INT PCV_VAL_UINT PCV_VAL_FLOAT +PCV_VAL_STRING PCV_VAL_BOOLEAN +%token PCT_INT PCT_UINT PCT_BOOLEAN PCT_FLOAT PCT_STRING +%token PCE_SYSTEM PCE_POOL PCE_PSET PCE_CPU + +%type <ival> PCV_VAL_INT +%type <uval> PCV_VAL_UINT +%type <bval> PCV_VAL_BOOLEAN +%type <dval> PCV_VAL_FLOAT +%type <sval> PCV_VAL_STRING +%type <sval> PCV_SYMBOL +%type <sval> PCV_FILENAME + +%type <ival> PCC_INFO +%type <ival> PCE_SYSTEM PCE_POOL PCE_PSET PCE_CPU +%type <ival> entity proptype info_entity modify_entity +%type <sval> name src tgt +%type <cmd> command +%type <cmd> list_command info_command edit_command create_command +destroy_command modify_command associate_command discover_command +rename_command transfer_command transfer_qty transfer_components +%type <prop> prop_remove prop_assign prop_op prop_ops property_list +%type <assoc> resource_assign resource_assigns resource_list +%type <assoc> component_assign component_assigns component_list +%type <val> value +%type <ival> resource component + +%% + +commands: command + { + if ($1->cmd != NULL) + $1->cmd($1); + free_cmd($1); + } + | commands command + { + if ($2->cmd != NULL) + $2->cmd($2); + free_cmd($2); + } + | command error { YYERROR;}; + +command: list_command + | edit_command + { + if (conf_edit_error != POE_OK) { + if ($1->cmd != parser_conf_create && + $1->cmd != parser_conf_discover) { + die(gettext(ERR_CONF_LOAD), conf_file, + get_errstr_err(conf_edit_error, + conf_edit_errno)); + } + } + edited = PO_TRUE; + }; + +list_command: info_command + { + if (conf_list_error != POE_OK) { + if ($1->cmd != parser_conf_create && + $1->cmd != parser_conf_discover) { + die(gettext(ERR_CONF_LOAD), conf_file, + get_errstr_err(conf_list_error, + conf_list_errno)); + } + } + } + | discover_command {conf_list_error = conf_edit_error = POE_OK;}; + +edit_command: create_command + | destroy_command + | modify_command + | associate_command + | transfer_command + | rename_command; + +info_command: PCC_INFO + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd = &parser_conf_info; + } + | PCC_INFO info_entity name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + switch ($2) { + case PCE_SYSTEM: + $$->cmd = &parser_conf_info; + break; + case PCE_POOL: + $$->cmd = &parser_pool_info; + break; + case PCE_PSET: + $$->cmd = &parser_pset_info; + break; + case PCE_CPU: + $$->cmd = &parser_cpu_info; + break; + default: + warn(gettext(ERR_UNKNOWN_ENTITY), $2); + YYERROR; + } + $$->cmd_tgt1 = $3; + }; + +create_command: PCC_CREATE entity name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + switch ($2) { + case PCE_SYSTEM: + $$->cmd = &parser_conf_create; + break; + case PCE_POOL: + $$->cmd = &parser_pool_create; + break; + case PCE_PSET: + $$->cmd = &parser_pset_create; + break; + default: + warn(gettext(ERR_UNKNOWN_ENTITY), $2); + YYERROR; + } + $$->cmd_tgt1 = $3; + } + | create_command property_list; + +destroy_command: PCC_DESTROY entity name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + switch ($2) { + case PCE_SYSTEM: + $$->cmd = &parser_conf_destroy; + break; + case PCE_POOL: + $$->cmd = &parser_pool_destroy; + break; + case PCE_PSET: + $$->cmd = &parser_pset_destroy; + break; + default: + warn(gettext(ERR_UNKNOWN_ENTITY), $2); + YYERROR; + } + $$->cmd_tgt1 = $3; + }; + +modify_command: PCC_MODIFY modify_entity name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + switch ($2) { + case PCE_SYSTEM: + $$->cmd = &parser_conf_modify; + break; + case PCE_POOL: + $$->cmd = &parser_pool_modify; + break; + case PCE_PSET: + $$->cmd = &parser_pset_modify; + break; + case PCE_CPU: + $$->cmd = &parser_cpu_modify; + break; + default: + warn(gettext(ERR_UNKNOWN_ENTITY), $2); + YYERROR; + } + $$->cmd_tgt1 = $3; + } + | modify_command property_list; + +associate_command: PCC_ASSOC PCE_POOL name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd = &parser_pool_associate; + cmd->cmd_tgt1 = $3; + } + | associate_command resource_list; + +transfer_command: transfer_qty + | transfer_components; + +transfer_components: PCC_TRANSFER PCK_TO PCE_PSET name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd = &parser_resource_xtransfer; + cmd->cmd_tgt1 = $4; + } + | transfer_components component_list; + +transfer_qty: PCC_TRANSFER PCV_VAL_UINT PCK_FROM PCE_PSET src PCK_TO tgt + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd = &parser_resource_transfer; + cmd->cmd_tgt1 = $5; + cmd->cmd_tgt2 = $7; + cmd->cmd_qty = $2; + } + | PCC_TRANSFER PCV_VAL_UINT PCK_TO PCE_PSET tgt PCK_FROM src + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd = &parser_resource_transfer; + cmd->cmd_tgt1 = $7; + cmd->cmd_tgt2 = $5; + cmd->cmd_qty = $2; + }; + +discover_command: PCC_DISC + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + $$->cmd = &parser_conf_discover; + }; + +rename_command: PCC_RENAME entity name PCK_TO name + { + if (($$ = alloc_cmd()) == NULL) + YYERROR; + cmd = $$; + switch ($2) { + case PCE_SYSTEM: + $$->cmd = &parser_conf_rename; + break; + case PCE_POOL: + $$->cmd = &parser_pool_rename; + break; + case PCE_PSET: + $$->cmd = &parser_pset_rename; + break; + default: + warn(gettext(ERR_UNKNOWN_ENTITY), $2); + YYERROR; + } + $$->cmd_tgt1 = $3; + $$->cmd_tgt2 = $5; + }; + +modify_entity: entity + | PCE_CPU {$$ = PCE_CPU;}; + +info_entity: entity + | PCE_CPU {$$ = PCE_CPU;}; + +entity: PCE_SYSTEM {$$ = PCE_SYSTEM;} + | PCE_POOL {$$ = PCE_POOL;} + | PCE_PSET {$$ = PCE_PSET;}; + +name: PCV_SYMBOL; + +src: PCV_SYMBOL; + +tgt: PCV_SYMBOL; + +value: PCV_VAL_INT { $$.i = $1;} + | PCV_VAL_UINT { $$.u = $1;} + | PCV_VAL_FLOAT { $$.d = $1;} + | PCV_VAL_BOOLEAN { $$.b = $1;} + | PCV_VAL_STRING { $$.s = $1;}; + +prop_remove: PCK_UNDEF proptype name + { + if (($$ = alloc_prop(po_remove)) == NULL) + YYERROR; + $$->prop_name = $3; + }; + +prop_op: prop_assign + | prop_remove; + +prop_ops: prop_op + { + prop_t *prop = NULL; + prop_t *prev = NULL; + + for (prop = cmd->cmd_prop_list; prop != NULL; + prop = prop->prop_next) + prev = prop; /* Find end of list */ + if (prev != NULL) + prev->prop_next = $1; + else + cmd->cmd_prop_list = $1; + $$ = cmd->cmd_prop_list; + } + | prop_ops PCK_SEPLST prop_op + { + prop_t *prop = NULL; + prop_t *prev = NULL; + + for (prop = cmd->cmd_prop_list; prop != NULL; + prop = prop->prop_next) + prev = prop; /* Find end of list */ + if (prev != NULL) + prev->prop_next = $3; + else + cmd->cmd_prop_list = $3; + $$ = cmd->cmd_prop_list; + + }; + +prop_assign: proptype name PCK_ASSIGN value + { + if (($$ = alloc_prop(po_create)) == NULL) + YYERROR; + $$->prop_name = $2; + switch ($1) { + case PCT_INT: + pool_value_set_int64($$->prop_value, $4.i); + break; + case PCT_UINT: + pool_value_set_uint64($$->prop_value, $4.u); + break; + case PCT_BOOLEAN: + pool_value_set_bool($$->prop_value, $4.b); + break; + case PCT_FLOAT: + pool_value_set_double($$->prop_value, $4.d); + break; + case PCT_STRING: + pool_value_set_string($$->prop_value, $4.s); + break; + } + }; + +property_list: PCK_OPENLST prop_ops PCK_CLOSELST + { + $$ = $2; + }; + +resource_assigns: resource_assign + { + assoc_t *assoc = NULL; + assoc_t *prev = NULL; + + for (assoc = cmd->cmd_assoc_list; assoc != NULL; + assoc = assoc->assoc_next) + prev = assoc; /* Find end of list */ + if (prev != NULL) + prev->assoc_next = $1; + else + cmd->cmd_assoc_list = $1; + $$ = cmd->cmd_assoc_list; + } + + | resource_assigns PCK_SEPLST resource_assign + { + assoc_t *assoc = NULL; + assoc_t *prev = NULL; + + for (assoc = cmd->cmd_assoc_list; assoc != NULL; + assoc = assoc->assoc_next) + prev = assoc; /* Find end of list */ + if (prev != NULL) + prev->assoc_next = $3; + $$ = $3; + }; + +resource_assign: resource name + { + if (($$ = alloc_assoc($1, $2)) == NULL) + YYERROR; + }; + +resource: PCE_PSET {$$ = PCE_PSET;}; + +resource_list: PCK_OPENLST resource_assigns PCK_CLOSELST + { + $$ = $2; + }; + +component_assigns: component_assign + { + assoc_t *assoc = NULL; + assoc_t *prev = NULL; + + for (assoc = cmd->cmd_assoc_list; assoc != NULL; + assoc = assoc->assoc_next) + prev = assoc; /* Find end of list */ + if (prev != NULL) + prev->assoc_next = $1; + else + cmd->cmd_assoc_list = $1; + $$ = cmd->cmd_assoc_list; + } + + | component_assigns PCK_SEPLST component_assign + { + assoc_t *assoc = NULL; + assoc_t *prev = NULL; + + for (assoc = cmd->cmd_assoc_list; assoc != NULL; + assoc = assoc->assoc_next) + prev = assoc; /* Find end of list */ + if (prev != NULL) + prev->assoc_next = $3; + $$ = $3; + }; + +component_list: PCK_OPENLST component_assigns PCK_CLOSELST + { + $$ = $2; + }; + +component_assign: component name + { + if (($$ = alloc_assoc($1, $2)) == NULL) + YYERROR; + }; + +component: PCE_CPU {$$ = PCE_CPU;}; + +proptype: PCT_INT {$$ = PCT_INT;} + | PCT_UINT {$$ = PCT_UINT;} + | PCT_BOOLEAN {$$ = PCT_BOOLEAN;} + | PCT_FLOAT {$$ = PCT_FLOAT;} + | PCT_STRING {$$ = PCT_STRING;}; + +%% + +#ifndef TEXT_DOMAIN +#define TEXT_DOMAIN "SYS_TEST" +#endif + +int +main(int argc, char *argv[]) +{ + int opt; + int docmd = PO_FALSE; + + (void) getpname(argv[0]); + (void) setlocale(LC_ALL, ""); + (void) textdomain(TEXT_DOMAIN); + if (atexit(terminate) != 0) { + die(gettext(ERR_SET_TERM), get_errstr()); + } + + conf_file = pool_static_location(); + + yydebug = 0; + while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) { + + switch (opt) { + case 'c': /* Process command line */ + if (dofile == PO_TRUE) + usage(1); + arg_parse(optarg); + docmd = PO_TRUE; + break; + case 'd': /* Manipulate dynamic configuration */ + conf_file = pool_dynamic_location(); + break; + case 'f': /* Process command file */ + if (docmd == PO_TRUE) + usage(1); + file_parse(optarg); + dofile = PO_TRUE; + break; + case 'h': + usage(2); + break; + case '?': + default: + usage(1); + break; + } + } + if (docmd == PO_FALSE && dofile == PO_FALSE) + usage(1); + + if (optind == argc - 1) { + if (strcmp(conf_file, pool_dynamic_location()) == 0) + usage(1); + conf_file = argv[optind]; + } else if (optind < argc - 1) + usage(1); + + if ((conf = pool_conf_alloc()) == NULL) { + die(gettext(ERR_ALLOC_ELEMENT), gettext(CONFIGURATION), + get_errstr()); + } + /* + * Opening a conf is complex, since we may be opening one of the + * following: + * - An existing configuration that we can modify + * - An existing configuration that we can't modify + * - A new configuration that we can modify + * - A new configuration that we can't modify + * The parser_conf_discover() function closes the file and reopens + * in PO_CREAT mode, so we only need be concerned here with the + * first two cases. + * Always try to open RDWR, if fail try RDONLY. Don't check + * if that fails, since we may be trying to discover a configuration + * in which case it's valid for both open attempts to fail. Later, when + * processing commands, if we don't have a valid configuration and + * we are trying to process a command which isn't a create or a discover + * we will fail the command as there is no valid configuration to + * work with. + */ + if (pool_conf_open(conf, conf_file, PO_RDWR) != 0) { + conf_edit_error = pool_error(); + conf_edit_errno = errno; + if (pool_conf_open(conf, conf_file, PO_RDONLY) != 0) { + conf_list_error = pool_error(); + conf_list_errno = errno; + } + } + + if (yyparse() == 0) { + if (pool_conf_status(conf) >= POF_VALID) { + if (pool_conf_validate(conf, POV_STRICT) == PO_FAIL) { + die(gettext(ERR_VALIDATION_FAILED), + get_errstr()); + } + /* + * If the user attempted to change the configuration, + * then we should try to save the changes. + */ + if (edited == PO_TRUE) { + if (pool_conf_commit(conf, 0) == PO_FAIL) { + die(gettext(ERR_CONFIG_SAVE_FAILED), + get_errstr()); + } + } + pool_conf_close(conf); + } + } else { + die(gettext(ERR_CMDPARSE_FAILED)); + } + + /* + * Cleanup is performed in terminate(), using atexit + */ + return (0); +} + +/* + * Info Commands + * Invoke the appropriate libpool info function and display the returned + * information. + */ +static void +parser_conf_info(cmd_t *cmd) +{ + char *info_buf; + const char *tgt = cmd->cmd_tgt1; + pool_value_t *pv = NULL; + pool_elem_t *pe; + + if ((pe = pool_conf_to_elem(conf)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + + if (tgt != NULL) + check_conf_name(cmd); + else { + if ((pv = pool_value_alloc()) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + if (pool_get_property(conf, pe, "system.name", pv) == + POC_INVAL || + pool_value_get_string(pv, &tgt) != PO_SUCCESS) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + } + if ((info_buf = pool_conf_info(conf, PO_TRUE)) == NULL) { + die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CONFIGURATION), + tgt, get_errstr()); + } + if (pv != NULL) { + pool_value_free(pv); + } + (void) printf("%s\n", info_buf); + free(info_buf); +} + +static void +parser_pool_info(cmd_t *cmd) +{ + pool_t *pool; + char *info_buf; + + if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); + + if ((info_buf = pool_info(conf, pool, PO_TRUE)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(POOL), + cmd->cmd_tgt1, get_errstr()); + (void) printf("%s\n", info_buf); + free(info_buf); +} + +static void +parser_resource_info(cmd_t *cmd, const char *type) +{ + pool_resource_t *resource; + char *info_buf; + + if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), + cmd->cmd_tgt1, get_errstr()); + + if ((info_buf = pool_resource_info(conf, resource, PO_TRUE)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(RESOURCE), + cmd->cmd_tgt1, get_errstr()); + (void) printf("%s\n", info_buf); + free(info_buf); +} + +static void +parser_pset_info(cmd_t *cmd) +{ + parser_resource_info(cmd, PSET); +} + +static void +parser_cpu_info(cmd_t *cmd) +{ + pool_component_t *comp; + char *info_buf; + + if ((comp = get_cpu(cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), + cmd->cmd_tgt1, get_errstr()); + if ((info_buf = pool_component_info(conf, comp, PO_TRUE)) == NULL) { + die(gettext(ERR_GET_ELEMENT_DETAILS), gettext(CPU), + cmd->cmd_tgt1, get_errstr()); + } + (void) printf("%s\n", info_buf); + free(info_buf); +} + +/* + * Create Commands + * Invoke the appropriate libpool create function and perform any requested + * property operations. + */ +static void +parser_conf_create(cmd_t *cmd) +{ + const char *tmp_name; + pool_elem_t *pe; + + if (conf != NULL && pool_conf_status(conf) >= POF_VALID) + pool_conf_close(conf); + if (pool_conf_open(conf, conf_file, PO_CREAT) != 0) { + die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), + cmd->cmd_tgt1, get_errstr()); + } + tmp_name = cmd->cmd_tgt1; + cmd->cmd_tgt1 = cmd->cmd_tgt2; + cmd->cmd_tgt2 = tmp_name; + parser_conf_rename(cmd); + if ((pe = pool_conf_to_elem(conf)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + prop_list_walk(cmd, pe); +} + +static void +parser_pool_create(cmd_t *cmd) +{ + pool_t *pool; + + if ((pool = pool_create(conf, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_CREATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); + prop_list_walk(cmd, pool_to_elem(conf, pool)); +} + +static void +parser_resource_create(cmd_t *cmd, const char *type) +{ + pool_resource_t *resource; + + if ((resource = pool_resource_create(conf, type, cmd->cmd_tgt1)) + == NULL) + die(gettext(ERR_CREATE_ELEMENT), type, cmd->cmd_tgt1, + get_errstr()); + + process_min_max(resource); + + prop_list_walk(cmd, pool_resource_to_elem(conf, resource)); +} + +static void +parser_pset_create(cmd_t *cmd) +{ + parser_resource_create(cmd, PSET); +} + +/* + * Rename Commands + * Rename the target by calling pool_put_property for the name property. + */ +static void +parser_rename(cmd_t *cmd, pool_elem_t *pe, const char *name) +{ + pool_value_t *pv; + + if ((pv = pool_value_alloc()) == NULL) { + die(gettext(ERR_ALLOC_ELEMENT), gettext(RESOURCE), + get_errstr()); + } + pool_value_set_string(pv, cmd->cmd_tgt2); + if (pool_put_property(conf, pe, name, pv) != 0) + die(gettext(ERR_PUT_PROPERTY), name, get_errstr()); + pool_value_free(pv); +} + +static void +parser_conf_rename(cmd_t *cmd) +{ + pool_elem_t *pe; + + if ((pe = pool_conf_to_elem(conf)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + + if (cmd->cmd_tgt1 != NULL) + check_conf_name(cmd); + + parser_rename(cmd, pe, SYSTEM_NAME); +} + +static void +parser_pool_rename(cmd_t *cmd) +{ + pool_t *pool; + + if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); + + parser_rename(cmd, pool_to_elem(conf, pool), POOL_NAME); +} + +static void +parser_pset_rename(cmd_t *cmd) +{ + pool_resource_t *resource; + + if ((resource = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(PSET), cmd->cmd_tgt1, + get_errstr()); + + parser_rename(cmd, pool_resource_to_elem(conf, resource), PSET_NAME); +} + +/* + * Destroy Commands + * Invoke the appropriate libpool destroy function to remove the target of the + * command from the configuration. + */ +static void +parser_conf_destroy(cmd_t *cmd) +{ + if (cmd->cmd_tgt1 != NULL) + check_conf_name(cmd); + + if (pool_conf_remove(conf) != 0) + die(gettext(ERR_DESTROY_ELEMENT), gettext(CONFIGURATION), + cmd->cmd_tgt1, get_errstr()); +} + +static void +parser_pool_destroy(cmd_t *cmd) +{ + pool_t *pool; + + if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); + + if (pool_destroy(conf, pool) != 0) + die(gettext(ERR_DESTROY_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); +} + +static void +parser_resource_destroy(cmd_t *cmd, const char *type) +{ + pool_resource_t *resource; + + if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), type, cmd->cmd_tgt1, + get_errstr()); + + if (pool_resource_destroy(conf, resource) != 0) + die(gettext(ERR_DESTROY_ELEMENT), type, cmd->cmd_tgt1, + get_errstr()); +} + +static void +parser_pset_destroy(cmd_t *cmd) +{ + parser_resource_destroy(cmd, PSET); +} + +/* + * Modify Commands + * Perform any requested property operations. + */ +static void +parser_conf_modify(cmd_t *cmd) +{ + pool_elem_t *pe; + + if ((pe = pool_conf_to_elem(conf)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + + if (cmd->cmd_tgt1 != NULL) + check_conf_name(cmd); + + prop_list_walk(cmd, pe); +} + +static void +parser_pool_modify(cmd_t *cmd) +{ + pool_t *pool; + + if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); + prop_list_walk(cmd, pool_to_elem(conf, pool)); +} + +static void +parser_resource_modify(cmd_t *cmd, const char *type) +{ + pool_resource_t *resource; + + if ((resource = pool_get_resource(conf, type, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), + cmd->cmd_tgt1, get_errstr()); + + process_min_max(resource); + + prop_list_walk(cmd, pool_resource_to_elem(conf, resource)); +} + +static void +parser_pset_modify(cmd_t *cmd) +{ + parser_resource_modify(cmd, PSET); +} + +static void +parser_cpu_modify(cmd_t *cmd) +{ + pool_component_t *comp; + + if ((comp = get_cpu(cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), + cmd->cmd_tgt1, get_errstr()); + prop_list_walk(cmd, pool_component_to_elem(conf, comp)); +} + +/* + * Discover Commands + * Invoke the libpool pool_conf_open function so that discovery will be + * performed. + */ + +/*ARGSUSED*/ +static void +parser_conf_discover(cmd_t *cmd) +{ + struct utsname utsname; + + if (strcmp(conf_file, pool_dynamic_location()) == 0) + return; + + if (uname(&utsname) < 0) + die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), + "unknown", get_errstr()); + + if (conf != NULL && pool_conf_status(conf) >= POF_VALID) + pool_conf_close(conf); + if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) != 0) { + die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), + utsname.nodename, get_errstr()); + } + if (pool_conf_export(conf, conf_file, POX_NATIVE) != 0) { + die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), + utsname.nodename, get_errstr()); + } + (void) pool_conf_close(conf); + if (pool_conf_open(conf, conf_file, PO_RDWR) != 0) { + die(gettext(ERR_CREATE_ELEMENT), gettext(CONFIGURATION), + utsname.nodename, get_errstr()); + } +} + +/* + * Associate Commands + * Walk the list of specified associations so that the target pool will be + * associated with the required resources. + */ + +static void +parser_pool_associate(cmd_t *cmd) +{ + pool_t *pool; + + if ((pool = pool_get_pool(conf, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(POOL), cmd->cmd_tgt1, + get_errstr()); + assoc_list_walk(cmd, pool); +} + +/* + * Assign Commands + * Walk the list of specified assignations so that the required + * components will be assigned to the target resource. + */ + +static void +parser_resource_xtransfer(cmd_t *cmd) +{ + pool_resource_t *resource; + + if ((resource = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), + cmd->cmd_tgt1, get_errstr()); + transfer_list_walk(cmd, resource); +} + +/* + * Transfer Commands + * Transfer the specified quantity of resource between the src and the tgt. + */ + +static void +parser_resource_transfer(cmd_t *cmd) +{ + pool_resource_t *src; + pool_resource_t *tgt; + + if ((src = pool_get_resource(conf, PSET, cmd->cmd_tgt1)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), + cmd->cmd_tgt1, get_errstr()); + if ((tgt = pool_get_resource(conf, PSET, cmd->cmd_tgt2)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(RESOURCE), + cmd->cmd_tgt2, get_errstr()); + if (pool_resource_transfer(conf, src, tgt, cmd->cmd_qty) != PO_SUCCESS) + die(gettext(ERR_XFER_QUANTITY), cmd->cmd_qty, + cmd->cmd_tgt1, cmd->cmd_tgt2, get_errstr()); +} + +/* + * arg_parse() puts the parser into command parsing mode. Create a tmpfile + * and instruct the parser to read instructions from this location by setting + * yyin to the value returned by tmpfile. Write the command into the file. + * Then seek back to to the start of the file so that the parser can read + * the instructions. + */ +static void +arg_parse(const char *command) +{ + if ((yyin = tmpfile()) == NULL) + die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); + if (fwrite(command, strlen(command), 1, yyin) != 1) + die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); + if (fseek(yyin, 0, SEEK_SET) != 0) + die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); +} + +/* + * file_parse() puts the parser into command file parsing mode. Firstly check + * to see if the user wishes to parse from standard input, if so do nothing. + * Attempt to open the specified file and instruct the parser to read + * instructions from this location by setting yyin to the value returned by + * fopen. + */ +static void +file_parse(const char *file) +{ + if (strcmp(file, "-") == 0) + return; + + if ((yyin = fopen(file, "r")) == NULL) { + die(gettext(ERR_CMD_FILE_INIT), strerror(errno)); + } +} + +/* + * free_cmd() releases the resources associated with the supplied cmd parameter. + */ +static void +free_cmd(cmd_t *cmd) +{ + prop_t *prop = cmd->cmd_prop_list; + assoc_t *assoc = cmd->cmd_assoc_list; + + free((void *)cmd->cmd_tgt1); + free((void *)cmd->cmd_tgt2); + while (prop != NULL) { + prop_t *tmp = prop; + prop = prop->prop_next; + pool_value_free(tmp->prop_value); + free((void *)tmp->prop_name); + free(tmp); + } + while (assoc != NULL) { + assoc_t *tmp = assoc; + assoc = assoc->assoc_next; + free((void *)tmp->assoc_name); + free(tmp); + } + free(cmd); +} + +/* + * alloc_cmd() allocates the required resources for a cmd_t. On failure, a + * warning is issued and NULL is returned. + */ +static cmd_t * +alloc_cmd(void) +{ + cmd_t *cmd; + + if ((cmd = malloc(sizeof (cmd_t))) == NULL) { + warn(gettext(ERR_CMD_LINE_ALLOC)); + return (NULL); + } + + (void) memset(cmd, 0, sizeof (cmd_t)); + + return (cmd); +} + +/* + * alloc_prop() allocates the required resources for a prop_t. On failure, a + * warning is issued and NULL is returned. The prop_t is initialised with + * the prop_op_t parameter. + */ +static prop_t * +alloc_prop(prop_op_t op) +{ + prop_t *prop; + + if ((prop = malloc(sizeof (prop_t))) == NULL) { + warn(gettext(ERR_PROP_ALLOC)); + return (NULL); + } + + (void) memset(prop, 0, sizeof (prop_t)); + if ((prop->prop_value = pool_value_alloc()) == NULL) { + warn(gettext(ERR_PROP_ALLOC)); + free(prop); + return (NULL); + } + prop->prop_op = op; + return (prop); +} + +/* + * alloc_assoc() allocates the required resources for an assoc_t. On failure, a + * warning is issued and NULL is returned. The assoc_t is initialised with + * the type and name of the association. + */ +static assoc_t * +alloc_assoc(int type, const char *name) +{ + assoc_t *assoc; + + if ((assoc = malloc(sizeof (assoc_t))) == NULL) { + warn(gettext(ERR_ASSOC_ALLOC)); + return (NULL); + } + (void) memset(assoc, 0, sizeof (assoc_t)); + assoc->assoc_type = type; + assoc->assoc_name = name; + return (assoc); +} + +/* + * check_conf_name() ensures the the name of the system in the configuration + * which is being manipulated matches the name of the system in the command. + * If not, the command is terminated with an appropriate error message. + */ +static void +check_conf_name(cmd_t *cmd) +{ + pool_value_t *pv; + const char *name; + pool_elem_t *pe; + + if ((pe = pool_conf_to_elem(conf)) == NULL) + die(gettext(ERR_GET_ELEMENT_DETAILS), + gettext(CONFIGURATION), "unknown", get_errstr()); + + + if ((pv = pool_value_alloc()) == NULL) { + die(gettext(ERR_ALLOC_ELEMENT), gettext(RESOURCE), + get_errstr()); + } + + if (pool_get_property(conf, pe, SYSTEM_NAME, pv) + == POC_INVAL) + die(gettext(ERR_GET_PROPERTY), gettext(SYSTEM_NAME), + get_errstr()); + + if (pool_value_get_string(pv, &name) == PO_FAIL) + die(gettext(ERR_GET_PROPERTY), gettext(SYSTEM_NAME), + get_errstr()); + + if (strcmp(cmd->cmd_tgt1, name) != 0) { + die(gettext(ERR_WRONG_SYSTEM_NAME), cmd->cmd_tgt1); + } + pool_value_free(pv); +} + +/* + * usage() display brief or verbose help for the poolcfg(1) command. + */ +static void +usage(int help) +{ + if (help >= 1) + (void) fprintf(stderr, gettext(USAGE1), cmdname, cmdname, + cmdname); + if (help >= 2) + (void) fprintf(stderr, gettext(USAGE2)); + exit(E_USAGE); +} + +/* + * prop_list_walk() walks the property manipulation requests and either puts + * or removes the property as appropriate. + */ +static void +prop_list_walk(cmd_t *cmd, pool_elem_t *pe) +{ + prop_t *prop; + + for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) { + switch (prop->prop_op) { + case po_create: + if (pool_put_property(conf, pe, prop->prop_name, + prop->prop_value) != 0) + die(gettext(ERR_PUT_PROPERTY), + prop->prop_name, get_errstr()); + break; + case po_remove: + if (pool_rm_property(conf, pe, prop->prop_name) != 0) + die(gettext(ERR_REMOVE_PROPERTY), + prop->prop_name, get_errstr()); + break; + } + } +} + +/* + * assoc_list_walk() walks the resource association requests and attempts + * to associate the pool with the specified resource. + */ +static void +assoc_list_walk(cmd_t *cmd, pool_t *pool) +{ + assoc_t *assoc; + + for (assoc = cmd->cmd_assoc_list; assoc != NULL; + assoc = assoc->assoc_next) { + pool_resource_t *resource; + + switch (assoc->assoc_type) { + case PCE_PSET: + if ((resource = pool_get_resource(conf, + PSET, assoc->assoc_name)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(PSET), + assoc->assoc_name, get_errstr()); + break; + default: + die(gettext(ERR_UNKNOWN_RESOURCE), + assoc->assoc_type); + break; + } + if (pool_associate(conf, pool, resource) != 0) + die(gettext(ERR_ASSOC_RESOURCE), assoc->assoc_name, + get_errstr()); + } +} + +/* + * transfer_list_walk() walks the component assign requests and attempts + * to assign the component with the specified resource. + */ +static void +transfer_list_walk(cmd_t *cmd, pool_resource_t *tgt) +{ + assoc_t *assoc; + + for (assoc = cmd->cmd_assoc_list; assoc != NULL; + assoc = assoc->assoc_next) { + pool_component_t *comp; + pool_resource_t *src; + pool_component_t *xfer[2] = {NULL}; + + if ((comp = get_cpu(assoc->assoc_name)) == NULL) + die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), + assoc->assoc_name, get_errstr()); + if ((src = pool_get_owning_resource(conf, comp)) == NULL) + die(gettext(ERR_XFER_COMPONENT), gettext(COMPONENT), + assoc->assoc_name, cmd->cmd_tgt1, get_errstr()); + xfer[0] = comp; + if (pool_resource_xtransfer(conf, src, tgt, xfer) != + PO_SUCCESS) + die(gettext(ERR_XFER_COMPONENT), gettext(COMPONENT), + assoc->assoc_name, cmd->cmd_tgt1, get_errstr()); + } +} + +/* + * terminate() is invoked when poolcfg exits. It cleans up + * configurations and closes the parser input stream. + */ +static void +terminate(void) +{ + if (conf != NULL) { + (void) pool_conf_close(conf); + pool_conf_free(conf); + } + if (yyin != stdin) + (void) fclose(yyin); +} + +/* + * get_cpu() takes the name of a CPU components and attempts to locate + * the element with that name. If the name is not formatted correctly + * (i.e. contains non-numeric characters) then the function terminates + * execution. If the components cannot be uniquely identified by the + * name, then NULL is returned. + */ +static pool_component_t * +get_cpu(const char *name) +{ + pool_component_t **components; + uint_t nelem; + int64_t sysid; + pool_value_t *vals[3] = {NULL}; + pool_component_t *ret; + const char *c; + + if ((vals[0] = pool_value_alloc()) == NULL) + return (NULL); + if ((vals[1] = pool_value_alloc()) == NULL) { + pool_value_free(vals[0]); + return (NULL); + } + if (pool_value_set_string(vals[0], "cpu") != PO_SUCCESS || + pool_value_set_name(vals[0], "type") != PO_SUCCESS) { + pool_value_free(vals[0]); + pool_value_free(vals[1]); + return (NULL); + } + + for (c = name; *c != NULL; c++) { + if (!isdigit(*c)){ + pool_value_free(vals[0]); + pool_value_free(vals[1]); + die(gettext(ERR_LOCATE_ELEMENT), gettext(CPU), + cmd->cmd_tgt1, gettext("CPU id should only contain " + "digits")); + } + } + sysid = strtoll(name, NULL, 0); + if (errno == ERANGE || errno == EINVAL) { + pool_value_free(vals[0]); + pool_value_free(vals[1]); + return (NULL); + } + pool_value_set_int64(vals[1], sysid); + if (pool_value_set_name(vals[1], CPU_SYSID) != PO_SUCCESS) { + pool_value_free(vals[0]); + pool_value_free(vals[1]); + return (NULL); + } + if ((components = pool_query_components(conf, &nelem, vals)) == + NULL) { + pool_value_free(vals[0]); + pool_value_free(vals[1]); + return (NULL); + } + if (nelem != 1) { + free(components); + pool_value_free(vals[0]); + pool_value_free(vals[1]); + return (NULL); + } + pool_value_free(vals[0]); + pool_value_free(vals[1]); + ret = components[0]; + free(components); + return (ret); +} + +/* + * process_min_max() ensures that "min" and "max" properties are + * processed correctly by poolcfg. libpool enforces validity + * constraints on these properties and so it's important that changes + * to them are supplied to the library in the correct order. + */ +void +process_min_max(pool_resource_t *resource) +{ + prop_t *minprop = NULL; + prop_t *maxprop = NULL; + prop_t *prop; + + /* + * Before walking the list of properties, it has to be checked + * to ensure there are no clashes between min and max. If + * there are, then process these properties immediately. + */ + for (prop = cmd->cmd_prop_list; prop != NULL; prop = prop->prop_next) { + const char *pos; + + if ((pos = strstr(prop->prop_name, min_suffix)) != NULL) + if (pos == prop->prop_name + strlen(prop->prop_name) + - 4) + minprop = prop; + if ((pos = strstr(prop->prop_name, max_suffix)) != NULL) + if (pos == prop->prop_name + strlen(prop->prop_name) + - 4) + maxprop = prop; + } + if (minprop && maxprop) { + pool_value_t *pv; + uint64_t smin, smax, dmax; + const char *type; + char *prop_name; + pool_elem_t *pe = pool_resource_to_elem(conf, resource); + + if ((pv = pool_value_alloc()) == NULL) + die(gettext(ERR_NOMEM)); + + (void) pool_get_property(conf, pe, "type", pv); + (void) pool_value_get_string(pv, &type); + + if ((prop_name = malloc(strlen(type) + strlen(max_suffix) + + 1)) == NULL) + die(gettext(ERR_NOMEM)); + + (void) sprintf(prop_name, "%s%s", type, max_suffix); + (void) pool_get_property(conf, pe, prop_name, pv); + (void) pool_value_get_uint64(pv, &dmax); + + (void) pool_value_get_uint64(minprop->prop_value, &smin); + + (void) pool_value_get_uint64(maxprop->prop_value, &smax); + if (smin < dmax) { + (void) pool_put_property(conf, pe, + minprop->prop_name, minprop->prop_value); + } else { + (void) pool_put_property(conf, pe, + maxprop->prop_name, maxprop->prop_value); + } + free((void *)prop_name); + pool_value_free(pv); + } +} diff --git a/usr/src/cmd/pools/poold/Makefile b/usr/src/cmd/pools/poold/Makefile new file mode 100644 index 0000000000..0dbe209449 --- /dev/null +++ b/usr/src/cmd/pools/poold/Makefile @@ -0,0 +1,144 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/Makefile + + +PROG = poold +OBJS = poold.o +SRCS = $(OBJS:%.o=%.c) + +include $(SRC)/cmd/Makefile.cmd + +JAVA_SUBDIRS = com/sun/solaris/service/exception \ + com/sun/solaris/service/kstat \ + com/sun/solaris/service/locality \ + com/sun/solaris/service/logging \ + com/sun/solaris/service/pools \ + com/sun/solaris/service/timer \ + com/sun/solaris/domain/pools + +SUBDIRS = libjkstat \ + libjlgrp \ + libjpool \ + libjsyslog + +all := TARGET = all +install := TARGET = install +clean := TARGET = clean +clobber := TARGET = clobber +lint := TARGET = lint +msg := TARGET = msg + +JARFILE = JPool.jar + +# JAVA_SUBDIRS and PACKAGEDOCS must be synchronized to ensure +# javadoc documentation is generated for all packages. + +PACKAGEDOCS = com.sun.solaris.service.exception \ + com.sun.solaris.service.kstat \ + com.sun.solaris.service.locality \ + com.sun.solaris.service.logging \ + com.sun.solaris.service.pools \ + com.sun.solaris.service.timer \ + com.sun.solaris.domain.pools +DOCDIR = doc +ROOTUSRLIBDRP = $(ROOTLIB)/pool +INCS = -I../common \ + -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris +LDLIBS += -lpool -L$(JAVA_ROOT)/jre/lib/$(MACH)/client -ljvm +LDFLAGS += -R$(JAVA_ROOT)/jre/lib/$(MACH)/client +LINTFLAGS += -erroff=E_NAME_USED_NOT_DEF2 +LINTLIBS += -L$(ROOTLIB) -lpool + +CPPFLAGS += $(INCS) +ROOTCMDDIR = $(ROOT)/usr/lib/pool + +CLOBBERFILES += $(JARFILE) + +# +# Definitions for message catalogue +# +POFILES = $(OBJS:.o=.po) + +# +# Definitions for Java installs +# + +JFILES = poold.properties $(JARFILE) +ROOTJAVA = $(JFILES:%=$(ROOTUSRLIBDRP)/%) + +$(ROOTJAVA) := FILEMODE = 444 +$(ROOTJAVA) := OWNER = root +$(ROOTJAVA) := GROUP = bin + +all: $(PROG) $(JAVA_SUBDIRS) $(JARFILE) \ + .WAIT $(SUBDIRS) + +clean : $(JAVA_SUBDIRS) $(SUBDIRS) + -$(RM) $(OBJS) $(POFILES) + +lint: $(SUBDIRS) + +msg: $(POFILES) + +install: $(ROOTCMD) $(JAVA_SUBDIRS) $(JARFILE) \ + .WAIT $(SUBDIRS) $(ROOTJAVA) + +$(JAVA_SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + if [ "$(TARGET)" != "clean" ] && [ "$(TARGET)" != "clobber" ]; \ + then \ + if [ ! -f $(JARFILE) ]; \ + then \ + $(JAR) -cf $(JARFILE) $@/*class; \ + else \ + $(JAR) -uf $(JARFILE) $@/*class; \ + fi \ + fi + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +doc: all + $(JAVADOC) -private -classpath $(JARFILE): -sourcepath . \ + -source 1.4 -d $(DOCDIR) $(PACKAGEDOCS) + +$(PROG): $(OBJS) + $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +$(ROOTUSRLIBDRP)/%: % + $(INS.file) + +FRC: + +lint: + $(LINT.c) $(PROG).c $(LINTLIBS) + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/DRM.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/DRM.java new file mode 100644 index 0000000000..15160174f1 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/DRM.java @@ -0,0 +1,86 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.domain.pools; + +/** + * The <code>DRM</code> interface specifies the contract between + * poold and higher level partitioning agents. + * + * <code>Poold</code> is designed to operate indepedently or as a + * member of a hierarchy of co-operating resource managers. In order + * to promote interaction and minimise implementation dependencies, + * the use of a common protocol which may be implemented in multiple + * languages is advocated. The protocol is provisionally named the + * "Distributed Resource Management" (DRM) protocol. + * + * This interface specifies how an implementation of the protocol + * would be implemented in Java. + * + * @see LogDRM + */ + +interface DRM { + /** + * Connect to a higher level partitioning agent. + * + * @param version The version of the protocol. + * @param url The location of the agent. + * @throws Exception If the connect fails. + */ + public void connect(int version, String url) throws Exception; + + /** + * Disconnect from a higher level partitioning agent. + * + * @throws Exception If the client is not connected. + */ + public void disconnect() throws Exception; + + /** + * Request resources via a higher level partitioning agent. + * + * @throws Exception If the request fails. + */ + public void request() throws Exception; + + /** + * Offer resources via a higher level partitioning agent. + * + * @throws Exception If the offer fails. + */ + public void offer() throws Exception; + + /** + * Cancel a previous offer or request. + * + * @throws Exception If the cancel fails. + */ + public void cancel() throws Exception; +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/DecisionHistory.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/DecisionHistory.java new file mode 100644 index 0000000000..f854231d9d --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/DecisionHistory.java @@ -0,0 +1,623 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.io.*; +import java.util.*; +import java.text.SimpleDateFormat; + +import com.sun.solaris.service.logging.*; +import com.sun.solaris.service.pools.*; + +/** + * This class maintains history about previous decisions. It can be + * used to ratify that a decision made on the basis of observed behavior + * over a limited time was historically shown to not degrade + * performance. The class maintains historical data in a history file. + * The format of this data is project-private and very likely to change + * as the implementation improves. + */ +public final class DecisionHistory implements Serializable { + /** + * The number of samples which a decision will be remembered. + */ + public static final int DECISION_LIFETIME = 256; + + /** + * Map of values of historical decisions. + */ + private HashMap decisions = new HashMap(); + + /** + * Map of resources to be monitored for improvement in + * utilization to the corresponding decision. Maps Resources to + * their decision's key string. + */ + private transient HashMap resourcesAwaitingImprovement = new HashMap(); + + /** + * List of decisions, in order of creation, to manage expiry. + */ + private transient LinkedList decisionList = new LinkedList(); + + /** + * Constructor. + */ + public DecisionHistory() + { + } + + /** + * Record a decision that's been made regarding a processor. + * Such a decision is a (cpuid, from-pset-name, to-pset-name, + * (from-pset-composition), (to-pset-composition), + * original-utilization-class) tuple. + */ + public void recordProcessorMove(ComponentMove move, + double startingUtilization, int sampleCount) throws PoolsException + { + Decision decision = Decision.forMove(move, startingUtilization); + decision.setStartingSampleCount(sampleCount); + Object o = decisions.put(decision.getKey(), decision); + Poold.OPT_LOG.log(Severity.DEBUG, "recorded decision (" + + decision + ")" + (o == null ? "" : " (displaced " + o + + ")")); + + /* + * Remember the most-recently-made decision regarding a + * resource until the next utilization sample is taken, + * so the next solve() may then reocrd the improvement. + * If another decision is made regarding this resource, + * the previous ones are forgotten, and their + * improvement fields are left 0. + */ + resourcesAwaitingImprovement.put(move.getTo(), + decision.getKey()); + decisionList.add(decision); + } + + private void recordImprovementWithUtilization(Resource resource, + double utilization) + { + String decisionKey = (String)resourcesAwaitingImprovement.get( + resource); + + if (decisionKey != null) { + Decision decision = (Decision)decisions.get( + decisionKey); + if (decision != null) { + decision.setImprovementWithNewUtilization( + utilization); + Poold.OPT_LOG.log(Severity.DEBUG, resource + + " improvement measured for decision " + + decision.describe()); + } + } + } + + /** + * A Decision boils down to a tuple describing the resource + * configuration involved before and after a particular resource + * is moved. We use a textual representation to describe the + * decision, by value, to avoid holding references to any of the + * actual resources involved. + */ + private static abstract class Decision implements Serializable { + /** + * Utilization of the resource before the move was made. + */ + private double startingUtilization = 0.0; + + /** + * Improvement in utilization (-1..1) after the move was + * made, if the determination is made. + */ + private double improvement = 0.0; + + /** + * Number of times this decision has been reexamined. + */ + private int usage = 0; + + /** + * Monitor's sample count when the decision was made, + * used to expire this decision after DECISION_LIFETIME + * samples. + */ + private int startingSampleCount; + + /** + * Decision's creation time. + */ + private Date date; + + /** + * Returns a String key for this Decision. + */ + public abstract String getKey(); + + /** + * Returns a Decision corresponding to a given Move. + * @return a Decision corresponding to a given Move. + * @throws InvalidArgumentException if there is no + * Decision type corresponding to the move. + */ + public static final Decision forMove(Move move, + double startingUtilization) + { + if (move instanceof ComponentMove) + return (new ComponentMoveDecision( + (ComponentMove)move, startingUtilization)); + else + return (null); + } + + private Decision() + { + date = new Date(); + } + + /** + * Invoked after construction, sets the utilization + * corresponding to the affected resource before the move + * was made. + */ + public final void setStartingUtilization( + double startingUtilization) + { + this.startingUtilization = startingUtilization; + } + + /** + * Invoked after construction, sets the sampleCount from + * the monitor, used to expire this decision after + * DECISION_LIFETIME samples. + */ + public void setStartingSampleCount(int sampleCount) + { + this.startingSampleCount = sampleCount; + } + + /** + * sampleCount accessor. + */ + public int getStartingSampleCount() + { + return (startingSampleCount); + } + + /** + * Stores the improvement, computed in a + * subclass-specific way. + */ + abstract public void setImprovementWithNewUtilization( + double newUtilization); + + /** + * Allow subclasses to record the improvement. + */ + protected void setImprovement(double improvement) + { + this.improvement = improvement; + } + + /** + * Returns the improvement in utilization measured by + * the monitor after the move is made. + */ + public final double getImprovement() + { + return (improvement); + } + + /** + * Returns the utilization corresponding to the affected + * resource before the move was made. + */ + public final double getStartingUtilization() + { + return (startingUtilization); + } + + public abstract int hashCode(); + public abstract boolean equals(Object o); + public abstract String toString(); + + private static final long serialVersionUID = 0x7860687; + + /** + * Number of times this decision has been reexamined. + */ + public final int getUsage() + { + return (usage); + } + + private final void incrementUsage() + { + usage++; + } + + /** + * Returns the time this decision was created. + */ + public final Date getDate() + { + return date; + } + + /** + * Formatter for printing creation date. + */ + private static SimpleDateFormat dateFormatter; + + /** + * Format for printing creation date. + */ + private final static String dateFormat = "MMM d kk:mm:ss"; + + /** + * Returns a more comprehensive textual representation + * of this devision than toString(). + */ + public final String describe() + { + if (dateFormatter == null) + dateFormatter = new SimpleDateFormat( + dateFormat); + return (toString() + " made at " + + dateFormatter.format(getDate()) + + " with improvement " + getImprovement() + + " used " + getUsage() + " times"); + } + } + + /** + * A Decision affecting the transfer of one CPU between + * processor sets. + */ + private static final class ComponentMoveDecision extends Decision { + /** + * The CPU Id of the involved CPU. + */ + private String cpuid; + + /** + * The name of the donating processor set. + */ + private String fromPsetName; + + /** + * The name of the receiving processor set. + */ + private String toPsetName; + + /** + * The string representation of the list of CPU IDs + * composing the donating set. + */ + private String fromPsetComposition; + + /** + * The string representation of the list of CPU IDs + * composing the receiving set. + */ + private String toPsetComposition; + + /** + * The number of CPUs in the receiving set, after the + * move is made. + */ + private int toPsetSize; + + /** + * A Decision-subclass-specific utilization group. + */ + private String utilizationClass; + + /** + * Constructs a ComponentMoveDecision based on the + * ComponentMove. + * @throws IllegalArgumentException if the ComponentMove + * can't be interpreted. + */ + public ComponentMoveDecision(ComponentMove move, + double startingUtilization) throws IllegalArgumentException + { + try { + cpuid = move.getComponents().toString(); + fromPsetName = move.getFrom().toString(); + toPsetName = move.getTo().toString(); + fromPsetComposition = move.getFrom() + .getComponents(null).toString(); + toPsetComposition = move.getTo() + .getComponents(null).toString(); + toPsetSize = move.getTo().getComponents(null) + .size(); + utilizationClass = computeUtilizationClass( + startingUtilization); + setStartingUtilization(startingUtilization); + } catch (PoolsException pe) { + throw(IllegalArgumentException)( + new IllegalArgumentException().initCause( + pe)); + } + } + + public String getKey() + { + StringBuffer sb = new StringBuffer(); + + sb.append(cpuid); + sb.append(", "); + sb.append(fromPsetName); + sb.append(", "); + sb.append(toPsetName); + + return (sb.toString()); + } + + public void setImprovementWithNewUtilization( + double newUtilization) + { + double sizeRatio = (double)(toPsetSize - 1) / + toPsetSize; + double expectedUtilization = sizeRatio * + getStartingUtilization(); + + Poold.OPT_LOG.log(Severity.DEBUG, + "pset improvement calculation expected " + + expectedUtilization + ", got " + newUtilization); + setImprovement(newUtilization - expectedUtilization); + } + + public int hashCode() { + return (((((cpuid.hashCode() ^ + fromPsetName.hashCode()) ^ toPsetName.hashCode()) ^ + fromPsetComposition.hashCode()) ^ + toPsetComposition.hashCode()) ^ + utilizationClass.hashCode()); + } + + public boolean equals(Object o) { + if (!(o instanceof ComponentMoveDecision)) + return false; + else { + ComponentMoveDecision cmd = + (ComponentMoveDecision)o; + return (cpuid.equals(cmd.cpuid) && + fromPsetName.equals(cmd.fromPsetName) && + toPsetName.equals(cmd.toPsetName) && + fromPsetComposition.equals( + cmd.fromPsetComposition) && + toPsetComposition.equals( + cmd.toPsetComposition) && + utilizationClass.equals( + cmd.utilizationClass)); + } + } + + /** + * Returns the group that this decision's utilization + * falls into. Presently, there is only one group, but + * ostensibly decisions will later be grouped (e.g. + * into control-zone-wide groups). + */ + private String computeUtilizationClass( + double startingUtilization) + { + return "I"; + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + + sb.append(cpuid.toString()); + sb.append(", "); + sb.append(fromPsetName.toString()); + sb.append(", "); + sb.append(toPsetName.toString()); + sb.append(", "); + sb.append(fromPsetComposition.toString()); + sb.append(", "); + sb.append(toPsetComposition.toString()); + sb.append(", "); + sb.append(utilizationClass.toString()); + + return (sb.toString()); + } + + private static final long serialVersionUID = 0xf7860687; + } + + /** + * Vetoes a Move only if there is a prior decision that showed a + * degradation in resource utilization. + */ + public boolean veto(Move m, double utilization) + { + Decision current = Decision.forMove(m, utilization); + Decision past; + + if (current != null) { + past = (Decision)decisions.get(current.getKey()); + if (past != null) + past.incrementUsage(); + if (past != null && past.getImprovement() < 0.0) { + Poold.OPT_LOG.log(Severity.DEBUG, m + + " vetoed by decision " + past.describe()); + return true; + } + } + + return false; + } + + private static final long serialVersionUID = 0xf7860687; + + /** + * Synchronize the decision history with the persistent version. + */ + public static DecisionHistory loadFromFile(String path) + throws IOException, ClassNotFoundException + { + return (load(new FileInputStream(path))); + } + + /** + * Synchronize the persistent decision history with the present + * history. + */ + public void syncToFile(String path) throws IOException + { + FileOutputStream fos = new FileOutputStream(path); + sync(fos); + fos.close(); + } + + /** + * Synchronize the decision history with the persistent version, + * from the given stream. + */ + public static DecisionHistory load(InputStream is) + throws IOException, ClassNotFoundException + { + ObjectInputStream ois = new ObjectInputStream(is); + + DecisionHistory dh = (DecisionHistory)ois.readObject(); + return (dh); + } + + /** + * Serialize the persistent decision history to the given + * stream. + */ + public void sync(OutputStream os) throws IOException + { + new ObjectOutputStream(os).writeObject(this); + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + + sb.append(decisions.keySet().size() + " decisions {"); + Iterator it = decisions.keySet().iterator(); + while (it.hasNext()) { + String dk = (String)it.next(); + Decision d = (Decision)decisions.get(dk); + + sb.append("\t("); + sb.append(d.describe()); + sb.append(")\n"); + } + sb.append("}"); + + return (sb.toString()); + } + + /** + * Measures the improvement in utilization of any resource for + * which a decision was recently made. + */ + public void expireAndMeasureImprovements(Monitor mon) + { + /* + * Measure the improvement in resources involved in + * recent decisions. + */ + if (mon.isValid()) { + for (Iterator it = resourcesAwaitingImprovement. + keySet().iterator(); it.hasNext(); ) { + Resource res = (Resource)it.next(); + try { + double utilization = mon. + getUtilization(res); + recordImprovementWithUtilization(res, + utilization); + } catch (StaleMonitorException sme) { + /* + * We can't access the utilization, so + * remove the decision. + */ + String decisionKey = (String) + resourcesAwaitingImprovement. + get(res); + if (decisionKey != null) + decisions.remove(decisionKey); + } + it.remove(); + } + } + + /* + * Expire decisions which have outlived + * DECISION_LIFETIME samples. + */ + int cutoff = mon.getSampleCount() - DECISION_LIFETIME; + if (cutoff > 0) { + Decision decision; + ListIterator it = decisionList.listIterator(0); + while (it.hasNext()) { + decision = (Decision)it.next(); + int sc = decision.getStartingSampleCount(); + if (sc < cutoff) { + if (sc > 0) { + Poold.OPT_LOG.log( + Severity.DEBUG, + "expiring decision (" + + decision + ")"); + it.remove(); + decisions.remove( + decision.getKey()); + } + } else + break; + } + } + } + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + + resourcesAwaitingImprovement = new HashMap(); + decisionList = new LinkedList(); + for (Iterator it = decisions.keySet().iterator(); + it.hasNext(); ) { + String decisionKey = (String)it.next(); + Decision decision = (Decision)decisions.get( + decisionKey); + decision.setStartingSampleCount(0); + decisionList.add(decision); + } + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Expression.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Expression.java new file mode 100644 index 0000000000..022d975f9a --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Expression.java @@ -0,0 +1,653 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.util.regex.*; + +/** + * This class provides the base implementation of an Expression. All + * types of Expression must inherit from this class. + * + * An objective is always specified in terms of an expression. The + * only recognized expressions are those known by this class. An + * expression is create using the valueOf() factory method, which is + * why Expressions must be known to this class. + */ +abstract class Expression +{ + /** + * Expression importance + */ + private long imp = -1; + + /** + * Expression name + */ + private String name; + + /** + * Sole constructor. (For invocation by subclass constructors) + */ + protected Expression(long imp, String name) + { + this.imp = imp; + this.name = name; + } + + /** + * Return the name of the expression. + */ + String getName() + { + return (this.name); + } + + /** + * Return the importance of the expression. + */ + long getImportance() + { + return (imp); + } + + /** + * Returns the supplied string as an expression. + * + * This utility function attempts to identify the supplied + * string as an expression. It tries in turn each of the known + * sub-classes until finally, if none can be recognized, an + * exception is thrown. This function is not immune to + * mistakenly mis-classifying an expression. It is the + * responsibility of the concrete Exrpession classes to ensure + * that syntactic integrity is maintained with respect to + * potential cases of mistaken identity. + * + * @param raw The candidate expression + * @throws IllegalArgumentException If no valid expression can + * be found + */ + static Expression valueOf(String raw) throws IllegalArgumentException + { + Expression exp = null; + /* + * TODO It would be better if subclasses registered, + * but this hard coded list will do until such a time + */ + if ((exp = KVOpExpression.valueOf(raw)) == null) + if ((exp = KVExpression.valueOf(raw)) == null) + exp = KExpression.valueOf(raw); + if (exp == null) + throw new IllegalArgumentException( + "unrecognized expression: " + raw); + return (exp); + } + + /** + * Ensure that the supplied importance is a valid value. + * + * @param imps String representation of the importance. + * + * @throws IllegalArgumentException if the importance is not + * valid. + */ + protected static long validateImportance(String imps) + throws IllegalArgumentException + { + long imp; + + try { + imp = Long.parseLong(imps); + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException("importance value " + + imps + " is not legal"); + } + + if (imp < 0) + throw new IllegalArgumentException("importance value " + + imps + " is not legal (must be positive)"); + return (imp); + } + + /** + * Ensure that the supplied keyword is a member of the + * supplied keys. + * + * @param keys Array of valid key strings. + * @param key Key sought. + * + * @throws IllegalArgumentException if the sought key is not + * a member of the keys array. + */ + protected static void validateKeyword(String keys[], String key) + throws IllegalArgumentException + { + for (int i = 0; i < keys.length; i++) { + if (keys[i].compareTo(key) == 0) + return; + } + throw new IllegalArgumentException("keyword " + key + + " is not recognized"); + } + + /** + * Return true if the supplied expression "contradicts" this + * expression. The definition of contradiction is left down to + * each implementing sub-class. + * + * @param o Expression to examine for contradiction. + */ + public abstract boolean contradicts(Expression o); +} + +/** + * This class implements the functionality for a key-value-operator + * expression. + * + * The general form of this expression is defined in the pattern + * member. A simplified rendition of which is: + * + * [[imp]:] <key> <op> <value> + * + * key is a string which identifies the expression + * op is the operator for the expression ( < | > | ~) + * value is the value of the expression + * + * For example: + * + * 10: utilization < 80 + */ +final class KVOpExpression extends Expression +{ + /** + * The operator for this expression. + */ + private char op; + + /** + * The value of this expression. + */ + private int val; + + /** + * The pattern used to recognize this type of expression. + */ + private static final Pattern pattern = Pattern.compile( + "\\s*((\\d+)\\s*:)?\\s*(\\w+)\\s*([~<>])\\s*(\\d+)\\s*"); + + /** + * The array of valid keys for this type of expression. + */ + private static final String keys[] = { "utilization" }; + + /** + * A greater than operator. + */ + static final char GT = '>'; + + /** + * A less than operator. + */ + static final char LT = '<'; + + /** + * A near to operator. + */ + static final char NT = '~'; + + /** + * Private constructor used in the valueOf() factory method. + * + * @param imp The importance of this expression. + * @param name The name of this expression. + * @param op The operator of this expression. + * @param val The value of this expression. + */ + private KVOpExpression(long imp, String name, String op, int val) + { + super(imp, name); + this.op = op.charAt(0); + this.val = val; + } + + /** + * Create and return an expression from the input string. + * + * Determine if the input string matches the syntax defined by + * this expression. If the expression cannot be matched, an + * exception will be thrown. + * + * @param raw Candidate expression string. + * + * @throws IllegalArgumentExpression if the string is not a + * valid expression of this type. + */ + static Expression valueOf(String raw) throws IllegalArgumentException + { + KVOpExpression exp = null; + Matcher m = pattern.matcher(raw); + + if (m.matches()) { + long imp = 1; + int val = Integer.parseInt(m.group(5)); + + if (m.group(2) != null) + imp = validateImportance(m.group(2)); + + validateKeyword(keys, m.group(3)); + if (val > 100 || val < 0) + throw new IllegalArgumentException( + "expression value " + val + + " is outside the legal range (0-100)"); + exp = new KVOpExpression(imp, m.group(3), + m.group(4), val); + } + return (exp); + } + + /** + * Return the operator for this expression. + */ + char getOp() + { + return (op); + } + + /** + * Return the value of this expression. + */ + int getValue() + { + return (val); + } + + /** + * Return a string representation of this expresssion. + */ + public String toString() + { + return ("(" + getImportance() + ", " + getName() + ", '" + op + + "', " + val + ")"); + } + + /** + * Indicates whether some other KVOpExpression is "equal to + * this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof KVOpExpression)) + return (false); + KVOpExpression other = (KVOpExpression) o; + if (getName().compareTo(other.getName()) != 0 || + op != other.getOp() || val != other.getValue()) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (getName().hashCode() + (int) op + val); + } + + /** + * Return true if the supplied expression "contradicts" this + * expression. If the supplied expression is not of the same + * type, then it cannot contradict it. If the names are + * different then there can be no contradiction. + * + * Contradiction occurs if the operator is the same or if they + * aren't the same and the operator is < or > and the values + * aren't simultanteously achievable. + * + * @param o Expression to examine for contradiction. + */ + public boolean contradicts(Expression o) + { + if (!(o instanceof KVOpExpression)) + return (false); + KVOpExpression other = (KVOpExpression) o; + if (getName().compareTo(other.getName()) != 0) + return (false); + if (getOp() != other.getOp()) { + if (getOp() != NT && other.getOp() != NT) { + if (getOp() == GT) { + if (getValue() < other.getValue()) + return (false); + } else { + if (getValue() > other.getValue()) + return (false); + } + } else + return (false); + } + return (true); + } +} + +/** + * This class implements the functionality for a key-value expression. + * + * The general form of this expression is defined in the pattern + * member. A simplified rendition of which is: + * + * [[imp]:] <key> <value> + * + * key is a string which identifies the expression + * value is the value of the expression + * + * For example: + * + * 10: locality tight + */ +final class KVExpression extends Expression +{ + /** + * The value of this expression. + */ + private String val; + + /** + * The pattern used to recognize this type of expression. + */ + private static final Pattern pattern = Pattern.compile( + "\\s*((\\d+)\\s*:)?\\s*(\\w+)\\s+(tight|loose|none)\\s*"); + + /** + * The array of valid keys for this type of expression. + */ + private static final String keys[] = { "locality" }; + + /** + * Private constructor used in the valueOf() factory method. + * + * @param imp The importance of this expression. + * @param name The name of this expression. + * @param val The value of this expression. + */ + private KVExpression(long imp, String name, String val) + { + super(imp, name); + this.val = val; + } + + /** + * Create and return an expression from the input string. + * + * Determine if the input string matches the syntax defined by + * this expression. If the expression cannot be matched, an + * exception will be thrown. + * + * @param raw Candidate expression string. + * + * @throws IllegalArgumentExpression if the string is not a + * valid expression of this type. + */ + static Expression valueOf(String raw) throws IllegalArgumentException + { + KVExpression exp = null; + Matcher m = pattern.matcher(raw); + + if (m.matches()) { + long imp = 1; + + if (m.group(2) != null) + imp = validateImportance(m.group(2)); + + validateKeyword(keys, m.group(3)); + exp = new KVExpression(imp, m.group(3), m.group(4)); + } + return (exp); + } + + /** + * Return the value of this expression. + */ + String getValue() + { + return (val); + } + + /** + * Return a string representation of this expresssion. + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + + buf.append("("); + buf.append(getImportance()); + buf.append(", "); + buf.append(getName()); + buf.append(", "); + buf.append(val); + buf.append(")"); + + return (buf.toString()); + } + + /** + * Indicates whether some other KVExpression is "equal to + * this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof KVExpression)) + return (false); + KVExpression other = (KVExpression) o; + if (getName().compareTo(other.getName()) != 0 || + val.compareTo(other.getValue()) != 0) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (getName().hashCode() + val.hashCode()); + } + + /** + * Return true if the supplied expression "contradicts" this + * expression. If the supplied expression is not of the same + * type, then it cannot contradict it. If the names are + * different then there can be no contradiction. + * + * Contradiction occurs if the value is different. + * + * @param o Expression to examine for contradiction. + */ + public boolean contradicts(Expression o) + { + if (!(o instanceof KVExpression)) + return (false); + KVExpression other = (KVExpression) o; + if (getName().compareTo(other.getName()) != 0) + return (false); + if (val.compareTo(other.getValue()) == 0) + return (false); + return (true); + } +} + +/** + * This class implements the functionality for a key expression. + * + * The general form of this expression is defined in the pattern + * member. A simplified rendition of which is: + * + * [[imp]:] <key> + * + * key is a string which identifies the expression + * + * For example: + * + * 10: wt-load + */ +final class KExpression extends Expression +{ + /** + * The pattern used to recognize this type of expression. + */ + private static final Pattern pattern = Pattern.compile( + "\\s*((\\d+)\\s*:)?\\s*([\\w-]+)\\s*"); + + /** + * The array of valid keys for this type of expression. + */ + private static final String keys[] = { "wt-load" }; + + /** + * Private constructor used in the valueOf() factory method. + * + * @param imp The importance of this expression. + * @param name The name of this expression. + */ + private KExpression(long imp, String name) + { + super(imp, name); + } + + /** + * Create and return an expression from the input string. + * + * Determine if the input string matches the syntax defined by + * this expression. If the expression cannot be matched, an + * exception will be thrown. + * + * @param raw Candidate expression string. + * + * @throws IllegalArgumentExpression if the string is not a + * valid expression of this type. + */ + static Expression valueOf(String raw) throws IllegalArgumentException + { + KExpression exp = null; + Matcher m = pattern.matcher(raw); + + if (m.matches()) { + long imp = 1; + + if (m.group(2) != null) + imp = validateImportance(m.group(2)); + + validateKeyword(keys, m.group(3)); + exp = new KExpression(imp, m.group(3)); + } + return (exp); + } + + /** + * Return a string representation of this expresssion. + */ + public String toString() + { + return ("(" + getImportance() + ", " + getName() + ")"); + } + + /** + * Indicates whether some other KExpression is "equal to + * this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof KExpression)) + return (false); + KExpression other = (KExpression) o; + if (getName().compareTo(other.getName()) != 0) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (getName().hashCode()); + } + + /** + * Return true if the supplied expression "contradicts" this + * expression. If the supplied expression is not of the same + * type, then it cannot contradict it. If the names are + * different then there can be no contradiction. + * + * @param o Expression to examine for contradiction. + */ + public boolean contradicts(Expression o) + { + if (!(o instanceof KExpression)) + return (false); + KExpression other = (KExpression) o; + if (getName().compareTo(other.getName()) != 0) + return (false); + return (true); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/LogDRM.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/LogDRM.java new file mode 100644 index 0000000000..0e6e516c2b --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/LogDRM.java @@ -0,0 +1,128 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.domain.pools; + +import java.util.*; +import java.util.logging.*; + +import com.sun.solaris.service.logging.Severity; +import com.sun.solaris.service.pools.*; + +/** + * The <code>LogDRM</code> class implements the Distributed Resource + * Management (DRM) protocol as a logger. + * + * All actions are logged using the logging facilities offered by + * <code>Poold</code>. + */ +class LogDRM implements DRM +{ + /** + * Supported protocol version. + */ + private final int version = 1; + + /** + * Location of higher level resource manager. + */ + private String url; + + /** + * Connect to a higher level partitioning agent. + * + * @param requested The requested version of the protocol. + * @param url The location of the agent. + * @throws Exception If the connect fails. + */ + public void connect(int requested, String url) throws Exception + { + if (requested > version) { + Poold.CONF_LOG.log(Severity.NOTICE, + "Requested protocol version (" + requested + + ") not supported"); + return; + } + this.url = url; + Poold.CONF_LOG.log(Severity.INFO, "DRM protocol version:" + + version + ", server: " + url); + } + + + /** + * Disconnect from a higher level partitioning agent. + * + * @throws Exception If the client is not connected. + */ + public void disconnect() throws Exception + { + Poold.CONF_LOG.log(Severity.INFO, "Disconnected from " + url); + } + + + /** + * Request resources via a higher level partitioning agent. + * + * TODO: Define request parameters. + * + * @throws Exception If the request fails. + */ + public void request() throws Exception + { + Poold.MON_LOG.log(Severity.INFO, "Requesting additional " + + "resources "); + } + + + /** + * Offer resources via a higher level partitioning agent. + * + * TODO: Define offer parameters. + * + * @throws Exception If the offer fails. + */ + public void offer() throws Exception + { + Poold.MON_LOG.log(Severity.INFO, "Requesting additional " + + "resources "); + } + + /** + * Canel a previous offer or request. + * + * TODO: Define cancel parameters. + * + * @throws Exception If the cancel fails. + */ + public void cancel() throws Exception + { + Poold.MON_LOG.log(Severity.INFO, "Requesting additional " + + "resources "); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Makefile new file mode 100644 index 0000000000..e99de5c8ad --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Makefile @@ -0,0 +1,60 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/domain/pools/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + +SOURCE = Move.java \ + Expression.java \ + Statistic.java \ + StatisticList.java \ + Monitor.java \ + Objective.java \ + ResourceMonitor.java \ + SystemMonitor.java \ + Solver.java \ + SystemSolver.java \ + DecisionHistory.java \ + DRM.java \ + LogDRM.java \ + Poold.java + +all install: $(SOURCE:.java=.class) + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *.class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Monitor.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Monitor.java new file mode 100644 index 0000000000..88d1841387 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Monitor.java @@ -0,0 +1,102 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.util.Map; + +import com.sun.solaris.service.pools.Configuration; +import com.sun.solaris.service.pools.Resource; +import com.sun.solaris.service.pools.PoolsException; + +/** + * A monitoring class. The user of this interface can retrieve + * monitoring information related to the configuration which is + * examined. + */ + +public interface Monitor { + /** + * Initialize the monitoring object using details from the + * supplied configuration. + * + * @param conf The configuration to be monitored. + * @throws PoolsException If the initialize fails. + * @throws StaleMonitorException If the resource monitors + * cannot be accessed. + */ + public void initialize(Configuration conf) throws PoolsException, + StaleMonitorException; + + /** + * Return the next sample. + * + * This call is a blocking call. The sample will only be + * returned after pausing the invoking thread for the "sample + * interval". + * + * @throws StaleMonitorException If the sample fails. + * @throws PoolsException If there is an error manipulating the + * pools configuration. + * @throws InterruptedException If the thread is interrupted + * while waiting for the sampling time to arrive. The caller + * may wish to check other conditions before possibly + * reinitiating the sample. + */ + public void getNext() throws StaleMonitorException, PoolsException, + InterruptedException; + + /** + * Return the number of samples taken. This is the number of + * successful calls to <code>getNext()</code>. + */ + public int getSampleCount(); + + /** + * Return the utilization for supplied resource. + * + * @param res The resource to be examined. + * + * @throws StaleMonitorException if the resource cannot be accessed. + */ + public double getUtilization(Resource res) throws StaleMonitorException; + public boolean isValid(); + public ResourceMonitor get(Resource res) throws StaleMonitorException; +} + +/** + * Indicates that a monitor must be re-initialized. This can occur + * for a number of reasons, including: + * + * <ul> + * <li><p> + * Resources created, modified, destroyed whilst sampling + * </ul> + */ +class StaleMonitorException extends Exception { +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Move.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Move.java new file mode 100644 index 0000000000..71d4aa423b --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Move.java @@ -0,0 +1,221 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.util.*; + +import com.sun.solaris.service.pools.*; + +/** + * This class represents a move of resources between two resource + * sets. It is designed to be extended by classes which implement + * different types of moves. + */ +abstract class Move +{ + /** + * Source resource set + */ + private Resource from; + + /** + * Destination resource set + */ + private Resource to; + + /** + * Sole constructor. (For invocation by subclass constructors) + * + * @param from The source of the move + * @param to The destination of the move + */ + protected Move(Resource from, Resource to) + { + this.from = from; + this.to = to; + } + + /** + * Return the source of this move. + */ + Resource getFrom() + { + return (from); + } + + /** + * Return the destination of this move. + */ + Resource getTo() + { + return (to); + } + + /** + * Apply this move to the resources described. + * + * @throws PoolsException If the move fails for any reason. + */ + abstract void apply() throws PoolsException; + + /** + * Return the quantity of moved resource. + */ + abstract long getQty(); +} + +/** + * This class represents a move of component resources between two + * resource sets. A component of a resource set is a uniquely + * identifiable component, such as a processor. + */ +final class ComponentMove extends Move +{ + /** + * List of components being moved. + */ + private List compList; + + /** + * Constructor + * + * @param from The source of the move + * @param to The destination of the move + * @param comp The component which is to be moved + */ + ComponentMove(Resource from, Resource to, Component comp) + { + super(from, to); + compList = new ArrayList(); + compList.add(comp); + } + + /** + * Return a list of the components that comprise this move. + * + * The members of the list are guaranteed to be Component + * objects. + */ + List getComponents() + { + return ((List) ((ArrayList) compList).clone()); + } + + /** + * Apply the move to the configuration to which the resources + * belong. + * + * @throws PoolsException if the transfer of resource fails. + */ + void apply() throws PoolsException + { + getTo().transfer(getFrom(), compList); + } + + /** + * Return the quantity of resource which is participating in + * this move. + */ + long getQty() + { + return (compList.size()); + } + + /** + * Converts the <code>ComponentMove</code> to a + * <code>String</code> of the form: + */ + public String toString() + { + return ("from " + getFrom().toString() + " to " + + getTo().toString() + " components " + compList); + } +} + +/** + * This class represents a move of commodity resources between two + * resource sets. Such a resource cannot be uniquely identified in the + * resource abstraction and is thus different to a move consisting of + * uniquely identifiable resource components. + */ +class QuantityMove extends Move +{ + /** + * The resource quantity of the move. + */ + private long qty; + + /** + * Construct a quantity move using the supplied details. + * + * @param from The source of the resources. + * @param to The destination of the resources. + * @param qty The quantity of the resources. + * + * @throws IllegalArgumentException if the qty is negative. + */ + QuantityMove(Resource from, Resource to, long qty) + { + super(from, to); + if (qty < 0) + throw new IllegalArgumentException( + "The resource quantity supplied (" + qty + + ") is illegal."); + this.qty = qty; + } + + /** + * Apply the move to the configuration to which the resources + * belong. + * + * @throws PoolsException if the transfer of resource fails. + */ + void apply() throws PoolsException + { + getTo().transfer(getFrom(), qty); + } + + /** + * Return the quantity of resource which is participating in + * this move. + */ + long getQty() + { + return (qty); + } + + /** + * Return a string representation of the move. + */ + public String toString() + { + return ("from " + getFrom().toString() + " to " + + getTo().toString() + " quantity " + qty); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Objective.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Objective.java new file mode 100644 index 0000000000..a242885bb2 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Objective.java @@ -0,0 +1,1034 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.text.DecimalFormat; +import java.util.*; +import java.util.logging.*; + +import com.sun.solaris.service.logging.Severity; +import com.sun.solaris.service.locality.*; +import com.sun.solaris.service.pools.*; + + +/** + * An objective interface. All classes which wish to contribute to the + * Objective Function (OF hence) calculation must implement this + * interface. This interface defines a strategy which can be used to + * make a contribution to the Objective Function calculation. + * + * The OF calculation (which is implemented by <code>Poold</code>) + * consists of determining all possible resource moves across all + * resources. Once all moves are known, all registered objectives + * (i.e. instances of this interface) are called and asked to value + * the move. + * + * Note, the output of this method is constrained to be between -1 and + * 1, representing minimum and maximum desirability of this move in + * terms of this objective. This is enforced by <code>Poold</code> and + * an <code>IllegalOFValueException</code> will be thrown if this + * constraint is broken. + */ +interface Objective +{ + /** + * Return the contribution of this objective. The contribution + * is constrainted to be a value between -1 and +1 to ensure + * that no objective can make a disproportionate contribution + * to the total result. + * + * The more desirable this move appears in terms of this + * objective, the closer to +1 will be the value. A value of 0 + * indicates that the move is neutral in terms of the + * objective. A negative value indicates that the move is + * undesirable. + * + * @param conf The configuration which is being examined + * @param move The move under consideration + * @param elem The element to which the objective applies + * + * @throws PoolsException if there is an error manipulating + * the configuration + */ + public double calculate(Configuration conf, Move move, Element elem) + throws PoolsException; + + /** + * Set the objective's expression to the supplied parameter. + * + * @param exp An expression for this objective. + */ + public void setExpression(Expression exp); + + /** + * Get the objective's expression. + */ + public Expression getExpression(); +} + +/** + * This interface must be implemented by all Objectives which are + * workload dependent. The examine method is used by a Solver to + * determine if the objective is still being satisfied. + */ +interface WorkloadDependentObjective extends Objective +{ + /** + * This method returns true if the Objective is no longer + * satisfied. If the objective is still satisfied, then return + * false. + * + * @param conf The configuration to be examined + * @param solver The solving interface used to get utilization + * information + * @param elem The element to which the objective belongs + * + * @throws PoolsException if there is an error examining the + * pool configuration + * @throws StaleMonitorException if there is an error accessing + * the element's ResourceMonitor + */ + public boolean examine(Configuration conf, Solver solver, + Element elem) throws PoolsException, StaleMonitorException; +} + +/** + * This class provides a skeletal implementation of the + * <code>Objective</code> interface to minimize the effort required + * to implement this interface. + * + * To implement an objective, the programmer need only to extend this + * class and add the name of the class into the appropriate element + * objectives property in the <code>poold.properties</code> file. + */ +abstract class AbstractObjective implements Objective +{ + abstract public double calculate(Configuration conf, Move move, + Element elem) throws PoolsException; + + /** + * The objectives which are recognized by this class + */ + private static Map objectives; + + /** + * The expression associated with this objective + */ + private Expression exp; + + /** + * Set the objective's expression to the supplied parameter. + * + * @param exp An expression for this objective. + */ + public void setExpression(Expression exp) + { + this.exp = exp; + } + + /** + * Get the objective's expression. + */ + public Expression getExpression() + { + return (exp); + } + + /** + * A factory method which returns a created objective which is + * associated with the supplied expression. The type and the + * expression are used to identify valid types of objectives + * to which this expression may be applied. If an acceptable + * objective cannot be found for the supplied type, then an + * <code>IllegalArgumentException</code> will be thrown. + * + * @param type The element type for which an objective must be + * found + * @param exp The expression which will be associated with the + * objective + * + * @throws IllegalArgumentExcetion if the supplied expression + * cannot be associated with an objective of the supplied type + */ + public static Objective getInstance(String type, Expression exp) + throws IllegalArgumentException + { + Objective ret = null; + Map typeObjs = null; + + initMapIfNecessary(); + typeObjs = (Map)objectives.get(type); + if (typeObjs != null) { + Class objClass = (Class)typeObjs.get(exp.getName()); + if (objClass != null) { + try { + ret = (Objective) objClass. + newInstance(); + } catch (Exception e) { + Poold.utility.die(Poold.OPT_LOG, e, + true); + } + ret.setExpression(exp); + } + } + if (ret == null) + throw new IllegalArgumentException( + "unrecognized objective name for " + type + ": " + + exp.toString()); + return (ret); + } + + /** + * Return a string representation of this objective. + */ + public String toString() + { + return (exp.toString()); + } + + /** + * Initialize the implementation map the first time it's + * called. + */ + private static void initMapIfNecessary() + { + /* + * Setup the objectives map for the known classes + */ + if (objectives == null) { + objectives = new HashMap(); + Properties props = new Properties(); + try { + props.load( + new FileInputStream( + Poold.POOLD_PROPERTIES_PATH)); + } catch (IOException ioe) { + Poold.utility.die(Poold.CONF_LOG, ioe); + } + registerObjectives(props, objectives, "system"); + registerObjectives(props, objectives, "pset"); + } + } + + /** + * Add the objectives contained in the supplied properties to + * the set of valid objectives. The objectives are updated + * with objectives of the supplied type contained in the + * properties. + * + * @param props The properties containing the objectives + * @param objectives The objectives to be updated + * @param type The type of objectives to be added + */ + private static void registerObjectives(Properties props, + Map objectives, String type) + { + Map typeObjs = new HashMap(); + String objs = props.getProperty(type + ".objectives"); + String objNames[] = objs.split(","); + for (int i = 0; i < objNames.length; i++) { + String objName = objNames[i].trim(); + try { + Class clazz = Class.forName(objName); + Field field = clazz.getDeclaredField("name"); + String key = (String) field.get(null); + typeObjs.put(key, clazz); + } catch (ClassNotFoundException cnfe) { + Poold.utility.die(Poold.CONF_LOG, cnfe); + } catch (NoSuchFieldException nsfe) { + Poold.utility.die(Poold.CONF_LOG, nsfe); + } catch (IllegalAccessException iae) { + Poold.utility.die(Poold.CONF_LOG, iae); + } + } + objectives.put(type, typeObjs); + } + + /** + * Indicates whether some other Objective is "equal to this + * one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof Objective)) + return (false); + Objective other = (Objective) o; + + return (getExpression().equals(other.getExpression())); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (getExpression().hashCode()); + } +} + + +/** + * The <code>WeightedLoadObjective</code> class implements a Weighted + * Load Objective for <code>Poold</code>. + * + * The goal is to allocate more resources to those resource partitions + * which are heavily loaded. The weighting is determined from the + * objective importance and the pool.importance. + */ +final class WeightedLoadObjective extends AbstractObjective + implements WorkloadDependentObjective +{ + /** + * The name of the class. + */ + static final String name = "wt-load"; + + /** + * The list of calculations made during examination. + */ + List calcList; + + /** + * Determine whether an objective is satisfied. If the + * objective is still satisfied, return false; otherwise + * return true. + * + * This objective examination determines if all resource sets + * are allocated the share of resources that their utilization + * would indicate they should be. This attempts to ensure that + * highly utilized resource sets recieve the greater + * proportion of available resources. + * + * @param conf The configuration to be examined + * @param solver The solving interface used to get utilization + * information + * @param elem The element to which the objective belongs + * + * @throws PoolsException if there is an error examining the + * pool configuration + * @throws StaleMonitorException if there is an error accessing + * the element's ResourceMonitor + */ + public boolean examine(Configuration conf, Solver solver, + Element elem) throws PoolsException, StaleMonitorException + { + Monitor mon = solver.getMonitor(); + Value val = new Value("type", "pset"); + List valueList = new LinkedList(); + calcList = new LinkedList(); + valueList.add(val); + + List resList = conf.getResources(valueList); + val.close(); + Iterator itRes = resList.iterator(); + + Calculation.totalUtil = 0; + Calculation.resQ = 0; + + while (itRes.hasNext()) { + Resource res = (Resource) itRes.next(); + List CPUs = res.getComponents(null); + + try { + Calculation calc = new Calculation(res, CPUs, + mon.getUtilization(res), + res.getLongProperty("pset.min"), + res.getLongProperty("pset.max")); + calcList.add(calc); + } catch (StaleMonitorException sme) { + Poold.MON_LOG.log(Severity.INFO, + res.toString() + + " not participating in " + toString() + + " calculatation as it has no " + + "available statistics."); + } + } + Iterator itCalc = calcList.iterator(); + while (itCalc.hasNext()) { + Calculation calc = (Calculation) itCalc.next(); + if (calc.getShare() != calc.comp.size()) { + Poold.MON_LOG.log(Severity.INFO, + elem.toString() + + " utilization objective not satisfied " + + toString() + " with desired share " + + calc.getShare() + " and actual share " + + calc.comp.size()); + return (true); + } + } + return (false); + } + + /** + * Holds data about weighted load calculations. This class is + * basically a structure which holds information specific to a + * weighted-load calculation + */ + static class Calculation { + /** + * The resource on which this calculation is based. + */ + Resource res; + + /** + * The list of component resources held by this resource. + */ + List comp; + + /** + * The utilization of this resource. + */ + double util; + + /** + * The minimum value of this resource's size. + */ + long min; + + /** + * The maximum value of this resource's size. + */ + long max; + + /** + * The total utilization of all instances of this class. + */ + static double totalUtil; + + /** + * The total quantity of resource for all instances of + * this class. + */ + static int resQ; + + /** + * Constructor. The class is immutable and holds + * information specific to a set of calculations about + * load. + * + * @param res The resource set + * @param comp The resource components + * @param util The resource utilization + * @param min The minimum qty of resource for this set + * @param max The maximum qty of resource for this set + */ + public Calculation(Resource res, List comp, double util, + long min, long max) + { + this.res = res; + this.comp = comp; + this.min = min; + this.max = max; + this.util = (util / 100) * comp.size(); + if (this.util < min) + this.util = min; + if (this.util > max) + this.util = max; + Calculation.totalUtil += this.util; + Calculation.resQ += comp.size(); + } + + /** + * Return the share of the total resource for this + * resource. + */ + long getShare() + { + if (totalUtil == 0) + return (min); + return (Math.round((util / totalUtil) * resQ)); + } + + public String toString() + { + StringBuffer buf = new StringBuffer(); + buf.append("res: " + res.toString()); + buf.append(" components: " + comp.toString()); + buf.append(" min: " + min); + buf.append(" max: " + max); + buf.append(" util: " + util); + buf.append(" total resource: " + resQ); + buf.append(" total utilization: " + totalUtil); + buf.append(" share: " + getShare()); + return (buf.toString()); + } + } + + /** + * Calculates the value of a configuration in terms of this + * objective. + * + * In the examination step, calculations of each resource's + * current and desired share were made. The moves can thus be + * assessed in terms of their desired impact upon the desired + * share. The current difference from desired is already + * known, so each move will serve to reduce or increase that + * difference. Moves that increase the difference have a + * negative score, those that reduce it have a positive + * score. All scores are normalized to return a value between + * -1 and 1. + * + * @param conf Configuration to be scored. + * @param move Move to be scored. + * @param elem The element to which the objective applies + * @throws PoolsException If an there is an error in execution. + */ + public double calculate(Configuration conf, Move move, Element elem) + throws PoolsException + { + double ret = 0; + Poold.OPT_LOG.log(Severity.DEBUG, + "Calculating objective type: " + name); + /* + * There shouldn't be any empty moves, but if there + * are they are rated at 0. + */ + if (move.getQty() == 0) + return (0); + Iterator itCalc = calcList.iterator(); + while (itCalc.hasNext()) { + Calculation calc = (Calculation) itCalc.next(); + long diff = calc.comp.size() - calc.getShare(); + + if (Math.abs(diff) > 1) { + double delta = 1 - + (move.getQty() / (double)Math.abs(diff)); + + if (calc.res.equals(move.getFrom())) { + if (diff > 0) + ret += delta; + else + ret -= delta; + } else if (calc.res.equals(move.getTo())) { + if (diff > 0) + ret -= delta; + else + ret += delta; + } + } else { + if (calc.res.equals(move.getFrom())) + ret += diff; + else if (calc.res.equals(move.getTo())) + ret -= diff; + } + + } + /* + * Normalize + */ + ret /= 2; + + Poold.MON_LOG.log(Severity.DEBUG, "ret: " + ret); + return (ret); + } +} + +/** + * A locality based objective which will assess moves in terms of + * their impact on the locality of the sets of resources which are + * impacted. + * + * The objective will assess moves with respect to the type of + * locality specified in the objective: + * + * <ul> + * <li><p> + * tight - resource locality is sought + * <li><p> + * loose - resource locality is avoided + * <li><p> + * none - resource locality has no impact + * </ul> + */ +final class LocalityObjective extends AbstractObjective +{ + /** + * The name of the class. + */ + static final String name = "locality"; + + /** + * The locality domain used to describe locality for this + * objective. + */ + private LocalityDomain ldom; + + /** + * Prepare the calculation for this objective for the resource + * to which it applies. + * + * @param ldom LocalityDomain containing these resources. + * @param res Resource to which this objective is applied. + * + * @throws PoolsException if accessing the supplied resource + * fails. + */ + public void prepare(LocalityDomain ldom, Resource res) + throws PoolsException + { + this.ldom = ldom; + } + + /** + * Calculates the value of a configuration in terms of this + * objective. + * + * Firstly check to see if it is possible to short-cut the + * calculation. If not, then start to examine the disposition + * of CPUs and locality groups in relation to the processor + * set being evaluated. The objective scores moves in terms of + * their impact upon the quotient of cpus contained in each + * locality group. + * + * @param conf Configuration to be scored. + * @param move Move to be scored. + * @param elem The element to which the objective applies + * @throws Exception If an there is an error in execution. + */ + public double calculate(Configuration conf, Move move, Element elem) + throws PoolsException + { + KVExpression kve = (KVExpression) getExpression(); + double ret = 0; + double qA = 0; + double qB = 0; + Resource res = (Resource) elem; + ComponentMove cm = (ComponentMove) move; + Poold.MON_LOG.log(Severity.DEBUG, + "Calculating objective type: " + name + " for: " + elem); + + /* + * If we are set to "none" then we don't care which + * configuration so just return 0 + */ + if (kve.getValue().compareTo("none") == 0) + return (ret); + /* + * If the maximum latency is 0, we don't care about + * latency + */ + if (ldom.getMaxLatency() == 0) + return (ret); + /* + * If this element doesn't participate in the move, we + * should return 0. + */ + if (elem.equals(move.getFrom()) == false && + elem.equals(move.getTo()) == false) + return (ret); + + /* + * Assess the effect on lgrp quotient for all + * moves. Try to maximise lgrp quotient for "tight" + * objectives and minimize if for "loose" objectives. + */ + /* + * All contained cpus + */ + List contains = res.getComponents(null); + /* + * All lgrps + */ + Set groups = ldom.foreignGroups(new HashSet(), contains); + + qB = calcQ(contains, groups); + + if (elem.equals(move.getFrom())) + contains.removeAll(cm.getComponents()); + else + contains.addAll(cm.getComponents()); + /* + * Recalculate lgrps to take account of new components + */ + groups = ldom.foreignGroups(new HashSet(), contains); + qA = calcQ(contains, groups); + + ret = qA - qB; + + if (kve.getValue().compareTo("loose") == 0) + ret = 0 - ret; + + Poold.MON_LOG.log(Severity.DEBUG, "ret: " + ret); + return (ret); + } + + /** + * Calculate a quotient using the supplied list of components + * and set of locality groups. The quotient represents the + * average (as in mean) number of CPUs (from the population in + * contains) present in each of the LocalityGroups contained + * in groups. + * + * @param contains The population of Components. + * @param groups The population of LocalityGroups. + * + * @throws PoolsException if there is an error accessing the + * CPUs. + */ + private double calcQ(List contains, Set groups) throws PoolsException + { + Iterator groupIt = groups.iterator(); + double q = 0.0; + while (groupIt.hasNext()) { + LocalityGroup grp = (LocalityGroup)groupIt.next(); + int cpu_ids[] = grp.getCPUIDs(); + Iterator containsIt = contains.iterator(); + int intersection = 0; + double total = 0; + while (containsIt.hasNext()) { + Component comp = (Component) containsIt.next(); + for (int i = 0; i < cpu_ids.length; i++) { + if (cpu_ids[i] == (int) comp. + getLongProperty("cpu.sys_id")) { + intersection++; + break; + } + } + } + double factor = 0; + for (int i = 1; i <= cpu_ids.length; i++) + factor += i; + factor = 1 / factor; + for (int i = 1; i <= intersection; i++) + q += i * factor; + } + q /= groups.size(); + return (q); + } +} + +/** + * A resource set utilization based objective which will assess moves + * in terms of their (likely) impact on the future performance of a + * resource set with respect to it's specified utilization objective. + * + * The utilization objective must be specified in terms of a + * KVOpExpression, see the class definition for information about the + * form of these expressions. The objective can be examined in terms + * of it's compliance with the aid of a monitoring object. The actual + * assessment of compliance is indicated by the associated monitoring + * object, with this class simply acting as a co-ordinator of the + * relevent information. + */ +final class UtilizationObjective extends AbstractObjective + implements WorkloadDependentObjective +{ + /** + * The name of the class. + */ + static final String name = "utilization"; + + /** + * Short run detection. + */ + private List zoneList = new LinkedList(); + + /** + * Format for printing utilization. + */ + private static final DecimalFormat uf = new DecimalFormat("0.00"); + + /** + * Solver used to calculate delta, i.e. gap, between target and + * actual utilization values. + */ + private Solver gapSolver; + + /** + * Determine whether an objective is satisfied. If the + * objective is still satisfied, return false; otherwise + * return true. + * + * The assessment of control is made by the monitoring class + * using the supplied Expression and resource. + * + * @param conf The configuration to be examined + * @param solver The solving interface used to get utilization + * information + * @param elem The element to which the objective belongs + * + * @throws PoolsException if there is an error examining the + * pool configuration + * @throws StaleMonitorException if there is an error accessing + * the element's ResourceMonitor + */ + public boolean examine(Configuration conf, Solver solver, + Element elem) throws PoolsException, StaleMonitorException + { + KVOpExpression kve = (KVOpExpression) getExpression(); + ResourceMonitor mon; + + /* + * If there is no resource monitor, then we cannot + * make an assessment of the objective's achievability. + * Log a message to make clear that this objective is + * not being assessed and then indicate that + * the objective has been achieved. + */ + try { + mon = solver.getMonitor().get((Resource)elem); + } catch (StaleMonitorException sme) { + Poold.MON_LOG.log(Severity.INFO, + elem.toString() + + " utilization objective not measured " + + toString() + " as there are no available " + + "statistics."); + return (false); + } + gapSolver = solver; + + double val = solver.getMonitor().getUtilization((Resource)elem); + + StatisticList sl = (StatisticList) mon.get("utilization"); + int zone = sl.getZone(kve, val); + + if (zoneList.size() == 9) { + zoneList.remove(0); + } + zoneList.add(new Integer(sl.getZoneMean(val))); + + /* + * Evaluate whether or not this objective is under + * control. + */ + if ((zone & StatisticOperations.ZONEZ) == + StatisticOperations.ZONEZ) { + /* + * If the objective is GT or LT, then don't + * return true as long as the objective is + * satisfied. + */ + if (kve.getOp() == KVOpExpression.LT && + (zone & StatisticOperations.ZONET) == + StatisticOperations.ZONELT) + return (false); + + if (kve.getOp() == KVOpExpression.GT && + (zone & StatisticOperations.ZONET) == + StatisticOperations.ZONEGT) + return (false); + Poold.MON_LOG.log(Severity.INFO, + elem.toString() + + " utilization objective not satisfied " + + toString() + " with utilization " + uf.format(val) + + " (control zone bounds exceeded)"); + return (true); + } + /* + * Check if our statistics need to be recalculated. + */ + checkShort(mon, elem, val); + return (false); + } + + /** + * Calculates the value of a configuration in terms of this + * objective. + * + * Every set must be classified with a control zone when this + * function is called. The move can be assessed in terms of + * the control violation type. zone violations which are minor + * are offered a lower contribution than more significant + * violations. + * + * @param conf Configuration to be scored. + * @param move Move to be scored. + * @param elem The element to which the objective applies + * @throws Exception If an there is an error in execution. + */ + public double calculate(Configuration conf, Move move, Element elem) + throws PoolsException + { + KVOpExpression kve = (KVOpExpression) getExpression(); + double ret; + + /* + * If the move is from the examined element, then + * check to see if the recipient has any + * objectives. If not, score the move poorly since we + * should never want to transfer resources to a + * recipient with no objectives. If there are + * objectives, then return the delta between target + * performance and actual performance for this + * element. + * + * If the move is to the examined element, then check + * to see if the donor has any objectives. If not, + * score the move highly, since we want to favour + * those resources with objectives. If there are + * objectives, return the delta between actual and + * target performance. + * + * If the element is neither the recipient or the + * donor of this proposed move, then score the move + * neutrally as 0. + */ + try { + double val, gap; + StatisticList sl; + + if (elem.equals(move.getFrom())) { + val = gapSolver.getMonitor(). + getUtilization(move.getFrom()); + sl = (StatisticList) gapSolver.getMonitor(). + get(move.getFrom()).get("utilization"); + gap = sl.getGap(kve, val) / 100; + + if (gapSolver.getObjectives(move.getTo()) == + null) { + /* + * Moving to a resource with + * no objectives should always + * be viewed unfavourably. The + * degree of favourability is + * thus bound between 0 and + * -1. If the source gap is + * negative, then subtract it + * from -1 to get the + * score. If positive, + * just return -1. + */ + if (gap < 0) { + ret = -1 - gap; + } else { + ret = -1; + } + } else { + ret = 0 - gap; + } + } else if (elem.equals(move.getTo())) { + val = gapSolver.getMonitor(). + getUtilization(move.getTo()); + sl = (StatisticList) gapSolver.getMonitor(). + get(move.getTo()).get("utilization"); + gap = sl.getGap(kve, val) / 100; + + if (gapSolver.getObjectives(move.getFrom()) == + null) { + /* + * Moving from a resource with + * no objectives should always + * be viewed favourably. The + * degree of favourability is + * thus bound between 0 and + * 1. If the destination gap + * is negative, then add to 1 + * to get the score. If + * positive, just return 1. + */ + if (gap < 0) { + ret = 0 - gap; + } else { + ret = 1; + } + } else { + ret = 0 + gap; + } + } else { + ret = 0; + } + } catch (StaleMonitorException sme) { + /* + * We should always find a monitor, + * but if we can't then just assume + * this is a neutral move and return + * 0. + */ + ret = 0; + } + Poold.MON_LOG.log(Severity.DEBUG, "ret: " + ret); + return (ret); + } + + /** + * Check whether or not a set's statistics are still useful + * for making decision.. + * + * Each set is controlled in terms of the zones of control + * based in terms of standard deviations from a mean. If the + * utilization of the set is not fluctuating normally around a + * mean, these checks will cause the accumulated statistics to + * be discarded and control suspended until a new sufficient + * set of data is accumulated. + * + * @param mon Resource monitor to examine. + * @param elem Element to which the resource monitor belongs. + * @param val Latest monitored value. + */ + private void checkShort(ResourceMonitor mon, Element elem, double val) + { + boolean checkOne = true; + int checkOnePos = 0; + boolean doCheckOne = false; + + Iterator itZones = zoneList.iterator(); + while (itZones.hasNext()) { + int zone = ((Integer) itZones.next()).intValue(); + if (doCheckOne) { + if (checkOne) { + if ((zone & StatisticOperations.ZONET) + != checkOnePos) { + checkOne = false; + } + } + } else { + if (zoneList.size() >= 9) { + checkOnePos = zone & + StatisticOperations.ZONET; + doCheckOne = true; + } + } + } + if (zoneList.size() >= 9 && checkOne) { + Poold.MON_LOG.log(Severity.INFO, + elem.toString() + + " utilization objective statistics reinitialized " + + toString() + " with utilization " + uf.format(val) + + " (nine points on same side of mean)"); + mon.resetData("utilization"); + zoneList.clear(); + } + } + +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Poold.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Poold.java new file mode 100644 index 0000000000..8ff1bd7fd5 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Poold.java @@ -0,0 +1,1155 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.io.*; +import java.util.*; +import java.util.logging.*; +import java.text.DecimalFormat; +import java.util.concurrent.atomic.*; + +import com.sun.solaris.service.locality.*; +import com.sun.solaris.service.logging.*; +import com.sun.solaris.service.pools.*; +import com.sun.solaris.service.exception.*; + +/* + * poold overview + * ----- -------- + * + * poold manipulates system resources in accordance with administrator + * specified constraints and objectives. The "goal" of the application + * is to maximise the efficiency of available resources within these + * parameters. + * + * Constraints are specified as follows: + * + * On a resource set: + * + * - min Is the minimum amount of resource a set should + * receive. poold will never elect to move resource so that a set + * falls below its minimum value. It is possible for a set to + * fall below its minimum as a consequence of administrative + * intervention, in which case poold will endeavour to bring a + * set back to its minimum level at the earliest opportunity. + * + * - max Is the maximum amount of resource a set should + * recieve. poold will never elect to move resource so that a set + * rises above its maximum value. It is possible for a set to + * rise above its maximum as a consequence of administrative + * intervention, in which case poold will endeavour to bring a + * set back to its maximum level at the earliest opportunity. + * + * On a resource component: + * + * - cpu.pinned Is an indication that a CPU should be ignored by + * poold for purposes of reallocation. A pinned CPU will never be + * moved by poold from one set to another. + * + * In addition to constraints, an administrator may also specify + * objectives. Currently three types of objectives are supported: + * + * - system.wt-load Is an objective set across an entire + * configuration. It attempts to ensure that resource is shared + * in accordance with current consumption. Those partitions which + * are most heavily utilized are give more resource in an attempt + * to lower their utilization levels. + * + * - set.locality Is a locality objective which attempts to + * minimize or maximize resource locality for a set. + * + * - set.utilization Is a utilization based objective which an + * administrator may use to explicitly dictate the utilization + * levels which should be achieved for a set. + * + * When executing, poold uses information about the current pools + * configuration; monitored resource utilization and specified + * constraints and objectives to determine if a move of resources is + * likely to lead to an increase in objective satisfaction. + * + * Candidate moves are generated by observing resource constraints. + * These moves are evaluated and scored in terms of their contribution + * to objective satisfaction (note: objectives are weighted according + * to their importance) and ranked accordingly. If a move can be + * identified that delivers an improvement, the move is made. Data is + * collected about past moves and recorded as "Decision History", + * before the move is made this data is consulted and if the move is + * expected not to yield an improvement, it may be cancelled. This + * refinement is designed to improve the quality of decision making by + * reflecting upon the past performance of decisions as well as the + * contribution to objective satisfaction. + * + * poold structure + * ----- --------- + * + * The common package name begins with: + * + * com.sun.solaris + * + * The software is divided into two main functional areas: + * + * service + * + * These packages collaborate to provide services to poold + * (typically, they use JNI to access exising + * functionality). They are not designed to be extended. For more + * details on these classes examine the source files in each + * directory. + * + * exception Stack trace formatter + * kstat Interface to Solaris kstat facility + * locality Interface to Solaris lgrp facility + * logging Interface to Solaris syslog facility + * pools Interface to Solaris libpool facility + * timer High resolution timestamps + * + * domain: + * + * These package reflect problem domain concepts and are + * responsible for application logic related to these + * concepts. + * + * pools Dynamic Resource Pools specific functionality. + * + * This code block will continue to explain in more detail how poold + * is organized. + * + * poold provides the following basic facilities: + * + * Monitoring: + * + * Basic statistic access is provided by the + * com.sun.solaris.service.kstat package. The following interfaces and + * classes collaborate to provide higher level statistic and + * monitoring facilities to the application: + * + * INTERFACES + * + * AggregateStatistic + * Monitor + * Statistic + * StatisticListener + * + * CLASSES + * + * AbstractStatistic + * DoubleStatistic + * LongStatistic + * ResourceMonitor + * StatisticEvent + * StatisticList + * StatisticOperations + * SystemMonitor + * UnsignedInt64Statistic + * + * Logging: + * + * Logging services are provided by the com.sun.solaris.logging + * package. In addition, the following class implements Poold's + * specific logging requirements. + * + * CLASSES + * + * Poold + * + * Optimization: + * + * lgrp service are provided by the com.sun.solaris.service.lgrp + * package. pools services are provided by the + * com.sun.solaris.service.pools package. In addition, optimization is + * implemented in the following Interfaces and Classes: + * + * INTERFACES + * + * Objective + * Solver + * WorkloadDependentObjective + * + * CLASSES + * + * AbstractObjective + * ComponentMove + * DecisionHistory + * Expression + * KExpression + * KVEpression + * KVOpExpression + * LocalityObjective + * Move + * Poold + * QuantityMove + * SystemSolver + * UtilizationObjective + * WeightedLoadObjective + * + * Configuration: + * + * pools services are provided by the com.sun.solaris.service.pools + * package, this is used to read poold configuration details from a + * libpool configuration. In addition, configuration is implemented in + * the following Classes: + * + * CLASSES + * + * AbstractObjective + * Expression + * Poold + * SystemSolver + * + * (NB: Some classes were mentioned in multiple categories where there + * responsbilities overlap. Inner classes are not listed as their + * responsibilities can be clearly inferred from their context.) + * + * For more details on any of the packages, classes or interfaces + * mentioned above, look at the documentation associated with each + * class. + */ + +/** + * The <code>Poold</code> class implements a dynamic resource + * allocation system for Solaris. + * + * <code>Poold</code> is a monitoring daemon, designed to evaluate + * user specified objectives, monitor workload behaviour and + * dynamically assign resources in order to satisfy the evaluated + * objectives. For more details see: + * + * <a href="http://sac.eng.sun.com/PSARC/2002/287/">PSARC/2002/287</a> + */ +final class Poold +{ + /** + * The configuration which is manipulated. + */ + private Configuration conf; + + /** + * The monitoring interface. + */ + private Monitor monitor; + + /** + * The interface to higher level resource managers. + */ + private DRM drm; + + /** + * The interface to the configuration solver. + */ + private Solver solver; + + /** + * Default path to the logging properties file. + */ + public static final String POOLD_PROPERTIES_PATH = + "/usr/lib/pool/poold.properties"; + + /** + * Logger for records which aren't produced in the Monitoring, + * Configuration, or Optimization states. This logger is the + * parent to the loggers used in those states. + */ + public static final Logger BASE_LOG = Logger.getLogger( + "com.sun.solaris.domain.pools.poold"); + + /** + * Logger for records produced in the Configuration state. + */ + public static final Logger CONF_LOG = Logger.getLogger( + "com.sun.solaris.domain.pools.poold.Configuration"); + + /** + * Logger for records produced in the Monitoring state. + */ + public static final Logger MON_LOG = Logger.getLogger( + "com.sun.solaris.domain.pools.poold.Monitoring"); + + /** + * Logger for records produced in the Optimization state. + */ + public static final Logger OPT_LOG = Logger.getLogger( + "com.sun.solaris.domain.pools.poold.Optimization"); + + /** + * Singleton instance of Poold. + */ + private static Poold instance; + + /** + * The main sampling and solving thread. + */ + private Thread mainThread; + + /** + * Process exit code indicating a failure. + */ + private static final int E_PO_FAILURE = 2; + + /** + * Keep track of whether initialize() has been invoked, to + * output the "starting" message on the first. + */ + private AtomicBoolean firstInitialization = new AtomicBoolean(true); + + /** + * Ignore configuration updates for the next interval? + */ + private boolean ignoreUpdates = true; + + /** + * Flags whether poold should run or exit. + */ + private AtomicBoolean shouldRun = new AtomicBoolean(true); + + private static class logHelper { + /** + * Default logfile location + */ + public static final String DEF_LOG_LOC = "/var/log/pool/poold"; + + /** + * Log location indicating <code>syslog</code>, as + * opposed to a file, should be used. + */ + public static final String SYSLOG_LOG_LOC = "SYSLOG"; + + /** + * Default Log severity (if not overridden) + */ + public static final Severity DEF_SEVERITY = Severity.INFO; + + /** + * Name of configuration property, log location. + */ + public static final String PROPERTY_NAME_LOG_LOC = + "system.poold.log-location"; + + /** + * Name of configuration property, log level. + */ + public static final String PROPERTY_NAME_LOG_LEVEL = + "system.poold.log-level"; + + /** + * Location of logfile -- an absolute filename, or + * "SYSLOG". + */ + private static String location; + + /** + * Logfile handler, responsible for taking log messages + * and exporting them. + */ + private static Handler handler; + + /** + * Logfile severity, log messages below this severity are + * ignored. + */ + private static Severity severity; + + /** + * Flag recording whether preinitialization has occurred. + */ + private static boolean preinitialized = false; + + /** + * Flag recording whether the logging Severity has been + * overridden with the -l command-line option, which + * means the console is the only thing being logged to, + * and the configuration's logging properties are + * ignored. + */ + private static boolean usingConsole; + + /** + * Indicates whether logging semantics should be changed + * to facilitate debugging. + */ + private static final boolean loggingDebugging = false; + + /** + * Do the pre-initialization initialization: install + * loggers for reporting errors during initialization. + * + * @param consoleSeverity If non-null, indicates that + * the configuration property-controlled logging behavior + * is to be overridden (the <code>-l</code> option was + * specified), and messages are to be logged only to the + * console, with (at most) the given maximum severity. + */ + private static void preinitialize(Severity consoleSeverity) { + if (preinitialized) + return; + + /* + * Read logging properties affecting the + * FileHandler and ConsoleHandler from + * <code>poold.properties</code>. + */ + Properties props = new Properties(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + props.load( + new FileInputStream(POOLD_PROPERTIES_PATH)); + props.store(bos, ""); + LogManager.getLogManager().readConfiguration( + new ByteArrayInputStream( + bos.toByteArray())); + } catch (IOException ioe) { + Poold.MON_LOG.log(Severity.WARNING, "could not " + + "read logging properties from " + + "poold.properties: " + ioe); + } + + if (consoleSeverity == null || loggingDebugging) { + /* + * Log messages to /var/log/pool/poold, + * the default location, until the pools + * configuration properties are read and + * applied, which may change the logging + * file and severity. + * + * Under normal circumstances, it's + * expected that NO INFO-level messages + * will be emitted until that time; this + * is only a measure to ensure that + * unanticipated errors are reported in + * some log. + */ + location = SYSLOG_LOG_LOC; + handler = SyslogHandler.getInstance("poold", + Facility.DAEMON); + severity = DEF_SEVERITY; + handler.setLevel(severity); + BASE_LOG.addHandler(handler); + } + + if (consoleSeverity != null) { + /* + * If -l is specified, log to the + * console. Unless loggingDebug is + * true, this will also mean that the + * logging properties are ignored. + * + * Determine if the user has specified + * the use of a ConsoleHandler through + * poold.properties. + */ + Logger root = Logger.getLogger(""); + Handler[] handler = root.getHandlers(); + ConsoleHandler ch = null; + for (int i = 0; i < handler.length && ch == + null; i++) + if (handler[i] + instanceof ConsoleHandler) + ch = (ConsoleHandler)handler[i]; + /* + * If none was previously, install a + * ConsoleHandler. + */ + if (ch == null) { + ch = new ConsoleHandler(); + + ch.setFormatter( + new SysloglikeFormatter()); + ch.setLevel(consoleSeverity); + root.addHandler(ch); + } + severity = consoleSeverity; + BASE_LOG.log(Severity.DEBUG, + "logging with level " + severity); + + /** + * Allow logging properties to be + * effective if loggingDebugging is not + * set. + */ + if (!loggingDebugging) + usingConsole = true; + } + preinitialized = true; + } + + /** + * Configure loggers based on the logging-related + * configuration properties. Outputs a description of + * any changes to the configuration logger. + * + * @throws ConfigurationException if there is an error + * applying libpool configuration properties to + * <code>poold</code> + */ + public static void initializeWithConfiguration( + Configuration conf) throws ConfigurationException + { + String newLogLocation; + Severity newLogSeverity; + String newLogSeverityName = null; + + /* + * Set the log location as specified by the + * configuration's system properties. + */ + try { + newLogLocation = conf.getStringProperty( + PROPERTY_NAME_LOG_LOC); + } catch (PoolsException e) { + newLogLocation = DEF_LOG_LOC; + } + + try { + newLogSeverityName = conf.getStringProperty( + PROPERTY_NAME_LOG_LEVEL); + newLogSeverity = Severity.getSeverityWithName( + newLogSeverityName); + assert(newLogSeverity != null); + } catch (PoolsException e) { + newLogSeverity = DEF_SEVERITY; + } catch (IllegalArgumentException e) { + throw(ConfigurationException) + (new ConfigurationException( + "invalid " + PROPERTY_NAME_LOG_LEVEL + + "value: " + newLogSeverityName) + .initCause(e)); + } + + Handler newLogHandler = null; + + /* + * (Re)install the logger for the poold class + * hierarchy. This means that only poold + * messages are controlled by the pools + * configuration properties/command-line + * options. + */ + + /* + * The logfile is always re-opened, in case the + * cause for reinitialization is due to SIGHUP + * following a log rotation. + */ + if (handler != null) { + BASE_LOG.removeHandler(handler); + handler.close(); + handler = null; + } + + if (newLogLocation.toUpperCase().equals( + SYSLOG_LOG_LOC.toUpperCase())) + newLogHandler = + SyslogHandler.getInstance("poold", + Facility.DAEMON); + else { + if (!newLogLocation.startsWith("/")) + throw + new ConfigurationException( + PROPERTY_NAME_LOG_LOC + + " value is not an" + + " absolute path"); + try { + newLogHandler = + new FileHandler( + newLogLocation, 0, 1, true); + newLogHandler.setFormatter( + new SysloglikeFormatter()); + } catch (java.io.IOException ioe) { + Poold.utility.die( + Poold.CONF_LOG, + new PooldException( + newLogLocation + + ": can't write") + .initCause(ioe), false); + } + } + + if (!severity.equals(newLogSeverity) || + !location.equals(newLogLocation)) + CONF_LOG.log(Severity.DEBUG, + "logging with level " + severity); + + severity = newLogSeverity; + handler = newLogHandler; + location = newLogLocation; + + handler.setLevel(severity); + BASE_LOG.addHandler(handler); + } + + /** + * Configure the loggers based on the pool's logging + * properties, or, if the -l option was specified on the + * command line, continue to use the console. + */ + public static void initialize(Configuration conf) + throws ConfigurationException + { + if (usingConsole) + return; + else + initializeWithConfiguration(conf); + } + + /** + * Return the current logging level. + */ + public static Severity getSeverity() + { + return (severity); + } + + public static void close() + { + if (handler != null) { + BASE_LOG.removeHandler(handler); + handler.close(); + } + } + } + + /** + * Constructor + * + * Only one poold instance should be running per system. + * + * @param consoleSeverity If non-null, indicates that the + * configuration property-controlled logging behavior is to be + * overridden (the <code>-l</code> option was specified), and + * messages are to be logged only to the console, with (at most) + * the given maximum severity. + */ + private Poold(Severity consoleSeverity) + { + /* + * Establish loggers for recording errors during + * initialization. Under normal circumstances, no + * messages will be emitted; this is only a measure to + * make sure that unanticipated errors are reported in + * some log, or the console, if the -l option is used. + */ + logHelper.preinitialize(consoleSeverity); + + /* + * Try opening the configuration read-write in hopes the + * ability will be possessed henceforth. + */ + try { + conf = new Configuration(PoolInternal. + pool_dynamic_location(), PoolInternal.PO_RDWR); + conf.close(); + } catch (PoolsException pe) { + Poold.utility.die(CONF_LOG, new PooldException( + "cannot open dynamic pools configuration " + + "read-write (" + pe.getMessage() + ")") + .initCause(pe), false); + } + + try { + conf = new Configuration(PoolInternal. + pool_dynamic_location(), PoolInternal.PO_RDONLY); + } catch (PoolsException pe) { + Poold.utility.die(CONF_LOG, pe); + } + + /* + * Create the required sub-components: + * - a monitoring object + * - a DRM implementer + * - a solver + */ + monitor = new SystemMonitor(); + drm = new LogDRM(); + solver = new SystemSolver(monitor); + } + + /** + * Returns a reference to the singleton <code>Poold</code>, + * constructing one if necessary. + * + * @param consoleSeverity If non-null, indicates that the + * configuration property-controlled logging behavior is to be + * overridden (the <code>-l</code> option was specified), and + * messages are to be logged only to the console, with (at most) + * the given maximum severity. + * @throws IllegalArgumentException if the given console + * severity doesn't match that of an existing instance. + */ + public static Poold getInstanceWithConsoleLogging( + Severity consoleSeverity) + { + if (instance == null) + return (instance = new Poold(consoleSeverity)); + else + if (logHelper.usingConsole == false && + consoleSeverity == null || consoleSeverity != + null && logHelper.getSeverity().equals( + consoleSeverity)) + return (instance); + else + throw new IllegalArgumentException(); + } + + /** + * Initializes <code>Poold</code> for operation at startup or + * in response to a detected libpool configuration change. + */ + private void initialize() + { + try { + logHelper.initialize(conf); + if (firstInitialization.get()) + CONF_LOG.log(Severity.INFO, "starting"); + /* + * When a system is extremely busy, it may + * prove difficult to initialize poold. Just + * keep trying until we succeed. + */ + boolean busy = true; + while (busy && shouldRun.get()) { + busy = false; + try { + monitor.initialize(conf); + CONF_LOG.log(Severity.DEBUG, + "configuring solver..."); + solver.initialize(conf); + CONF_LOG.log(Severity.INFO, + "configuration complete"); + } catch (PoolsException pe) { + CONF_LOG.log(Severity.INFO, + "The system is too busy to " + + "initialize, attempting " + + "initialization again"); + /* + * pause for a while before + * re-attempting the + * initialization. + */ + try { + Thread.sleep(50); + } catch (InterruptedException ie) { + /* + * Safe to ignore this + * exception as we + * will simply try + * again sooner. + */ + } + busy = true; + } catch (StaleMonitorException sme) { + CONF_LOG.log(Severity.INFO, + "The system is too busy to " + + "initialize, attempting " + + "initialization again"); + /* + * pause for a while before + * re-attempting the + * initialization. + */ + try { + Thread.sleep(50); + } catch (InterruptedException ie) { + /* + * Safe to ignore this + * exception as we + * will simply try + * again sooner. + */ + } + busy = true; + } + } + if (firstInitialization.get()) + firstInitialization.set(false); + } catch (ConfigurationException ce) { + Poold.utility.die(CONF_LOG, ce); + } + } + + /** + * Execute <code>Poold</code> indefinitely. This method is + * invoked after <code>Poold</code> completes + * configuration. It will continue to execute until + * <code>Poold</code> is terminated. + * + * @throws Exception If an there is an error in execution. + */ + private void execute() throws Exception + { + int changed = 0; + boolean confRequired = false; + + while (shouldRun.get()) { + try { + changed = conf.update(); + /* + * poold modifies the configuration + * during startup (updating the PID of + * poold) so we have to ignore our + * first ever configuration update. + */ + if (ignoreUpdates) { + ignoreUpdates = false; + changed = 0; + } + assert(!confRequired || confRequired && + changed != 0); + if (changed != 0) { + CONF_LOG.log(Severity.DEBUG, + "configuration change detected"); + if (!confRequired) + CONF_LOG.log(Severity.INFO, + "configuration changed " + + "externally"); + CONF_LOG.log(Severity.INFO, + "reconfiguring..."); + } + confRequired = false; + } catch (PoolsException pe) { + Poold.utility.die(CONF_LOG, pe); + } + if (changed != 0) + initialize(); + + boolean gotNext = false; + while (shouldRun.get() && !gotNext) { + try { + monitor.getNext(); + gotNext = true; + + /* + * All workload-dependent + * objectives must now be + * checked for violations. The + * solver holds all objectives + * and it makes the decision + * about whether a + * reconfiguration is required. + */ + if (solver.examine(monitor)) { + MON_LOG.log(Severity.INFO, + "reconfiguration required"); + confRequired = solver.solve(); + } else { + MON_LOG.log(Severity.INFO, + "all evaluated objectives" + + " satisfied"); + } + } catch (StaleMonitorException e) { + /* + * Later, assert that every + * cause of the + * StaleMonitorException is + * handled by the above + * conf.update(). + */ + confRequired = true; + } catch (InterruptedException ie) { + Poold.MON_LOG.log(Severity.INFO, + "interrupted"); + break; + } + } + if (!shouldRun.get()) + break; + System.runFinalization(); + } + Poold.BASE_LOG.log(Severity.NOTICE, "exiting"); + } + + /** + * Cleanup any resources when the application terminates. + */ + private void cleanup() + { + conf.close(); + logHelper.close(); + instance = null; + } + + /** + * Invoke <code>Poold</code>. This main function is provided + * so that <code>poold</code> can be executed. Execution will + * continue indefinitely unless there is an error, in which case + * when execute() terminates. + */ + public void run() + { + mainThread = Thread.currentThread(); + + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + try { + cleanup(); + } catch (Throwable t) { + } + } + }); + + try { + initialize(); + execute(); + } catch (Throwable t) { + Poold.utility.die(BASE_LOG, t); + } + } + + /** + * Stops <code>Poold</code>. Sets a flag indicating that run() + * should break out of the monitor/solve loop and clean up. + */ + public void shutdown() { + /* + * Flag that the main thread should break out of the + * sample/solve loop as soon as possible. + */ + shouldRun.set(false); + + /* + * Interrupt the main thread, which will cause the + * monitor to break out of its sleep if it's waiting for + * the sample time to arrive, and cause the sample/solve + * loop condition to be evaluated sooner. But make some + * effort not to cause an InterruptedIOException if + * we're not even through initialization yet; we'll get + * around to shutting down soon enough. + */ + if (!firstInitialization.get() && mainThread != null) + mainThread.interrupt(); + } + + public static void main(String args[]) throws IllegalArgumentException + { + Severity severity = null; + + if (args.length > 0) { + if (args[0].compareTo("-l") == 0 && args.length == 2) { + severity = (Severity) Severity.parse(args[1]); + } else + throw new IllegalArgumentException( + "usage: poold [-l level]"); + } + Poold p = getInstanceWithConsoleLogging(severity); + p.run(); + } + + /** + * The <code>utility</code> class provides various + * <code>Poold</code> related static utility methods that + * don't naturally reside on any class. + */ + static class utility { + /** + * Outputs a near-final message corresponding + * to an exception (or other throwable) to the named + * logger before causing the VM to exit. The message + * will have ERROR severity unless an instance of + * PoolsException is given, in which case the message + * will adopt the PoolsException's severity. Similarly, + * if the PoolsException specifies an exit code, it will + * be used; otherwise the default of + * <code>E_PO_FAILURE</code> will be used. + * + * @param logger Logger used to log the message + * @param t The cause. A stack trace will be affixed to + * the message. + */ + public static void die(Logger logger, Throwable t) + { + die(logger, t, true); + } + + /** + * Outputs a near-final message corresponding + * to an exception (or other throwable) to the named + * logger before causing the VM to exit. The message + * will have ERROR severity unless an instance of + * PoolsException is given, in which case the message + * will adopt the PoolsException's severity. Similarly, + * if the PoolsException specifies an exit code, it will + * be used; otherwise the default of + * <code>E_PO_FAILURE</code> will be used. + * + * @param logger Logger used to log the message + * @param t The cause. + * @param showStackTrace If true, a stack trace will be + * affixed to the message. + */ + public static void die(Logger logger, Throwable t, + boolean showStackTrace) + { + try { + Severity severity; + /* + * Configure the message's exception and + * severity. + */ + LogRecord record; + if (t instanceof PooldException) + record = new LogRecord( + ((PooldException)t).getSeverity(), + t.getMessage()); + else + record = new LogRecord(Severity.ERR, + t.getMessage()); + if (record.getMessage() == null) + record.setMessage("exception " + + t.getClass().getName()); + if (showStackTrace) + record.setThrown(t); + + record.setLoggerName(logger.getName()); + logger.log(record); + + if (logHelper.handler != null) + logHelper.handler.flush(); + if (t instanceof PooldException) + System.exit(((PooldException)t) + .getExitCode()); + else + System.exit(E_PO_FAILURE); + } catch (Exception e) { + SuccinctStackTraceFormatter.printStackTrace(e); + System.exit(-1); + } + } + + /** + * Outputs a warning-level message to the named logger. + * + * @param logger Logger used to log the message + * @param t The cause. + * @param showStackTrace If true, a stack trace will be + * affixed to the message. + */ + public static void warn(Logger logger, Throwable t, + boolean showStackTrace) + { + try { + Severity severity; + /* + * Configure the message's exception and + * severity. + */ + LogRecord record; + if (t instanceof PooldException) + record = new LogRecord( + ((PooldException)t).getSeverity(), + t.getMessage()); + else + record = new LogRecord(Severity.WARNING, + t.getMessage()); + if (record.getMessage() == null) + record.setMessage("exception " + + t.getClass().getName()); + if (showStackTrace) + record.setThrown(t); + + record.setLoggerName(logger.getName()); + logger.log(record); + + if (logHelper.handler != null) + logHelper.handler.flush(); + } catch (Exception e) { + SuccinctStackTraceFormatter.printStackTrace(e); + System.exit(-1); + } + } + } +} + +class ConfigurationException extends Exception +{ + public ConfigurationException(String message) + { + super(message); + } +} + +class IllegalOFValueException extends RuntimeException +{ + public IllegalOFValueException(String message) + { + super(message); + } +} + +class PooldException extends Exception { + /** + * The exit code which the virtual machine should exit at if + * this exception cannot be handled. + */ + private int exitCode; + + /** + * The severity of this message. See <code>Severity</code>. + */ + private Severity severity; + + /** + * Constructs a message with default exit code and + * <code>System.ERR</code> severity. + */ + public PooldException(String message) + { + this(message, 1, Severity.ERR); + } + + /** + * Constructs a message with given exit code and + * <code>System.ERR</code> severity. + */ + public PooldException(String message, int exitCode) + { + this(message, exitCode, Severity.ERR); + } + + /** + * Constructs a message with a given exit code and severity. + */ + public PooldException(String message, int exitCode, Severity severity) + { + super(message); + this.exitCode = exitCode; + this.severity = severity; + } + + /** + * The exit code which the virtual machine should exit at if + * this exception cannot be handled. + */ + public int getExitCode() + { + return (exitCode); + } + + public Severity getSeverity() + { + return (severity); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/ResourceMonitor.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/ResourceMonitor.java new file mode 100644 index 0000000000..36280e425e --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/ResourceMonitor.java @@ -0,0 +1,255 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.math.BigInteger; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Iterator; +import com.sun.solaris.service.pools.Component; +import com.sun.solaris.service.pools.Resource; +import com.sun.solaris.service.pools.PoolsException; +import com.sun.solaris.service.pools.UnsignedInt64; + +/** + * This represents a monitored resource and the techniques used to + * monitor the resource. + */ +class ResourceMonitor extends HashMap +{ + /** + * The monitored resource. + */ + private Resource target; + + /** + * The size of the statistic buffer. + */ + private final int maxSize; + + /** + * Cached list of components to be monitored. + */ + private LinkedList compList; + + /** + * Constructor. No monitor target and a default buffer size of + * 50. + */ + public ResourceMonitor() + { + this(null, 50); + } + + /** + * Constructor. + * + * @param target The resource to be monitored. + * @param maxSize The maximum number of samples to be held. + */ + public ResourceMonitor(Resource target, int maxSize) + { + super(); + this.target = target; + this.maxSize = maxSize; + compList = new LinkedList(); + + } + + /** + * Initialize the resource monitor with it's list of + * components. Components which are off-line or powered-off + * cannot be monitored, so they should be removed from the + * list of components. + * + * @throws PoolsException if there is an error accessing the + * pool elements. + */ + public void initialize() throws PoolsException + { + compList.clear(); + List candidates = target.getComponents(null); + Iterator candIt = candidates.iterator(); + while (candIt.hasNext()) { + Component comp = (Component) candIt.next(); + String status = comp.getStringProperty("cpu.status"); + if (status.compareTo("off-line") != 0 && + status.compareTo("powered-off") != 0) + compList.add(comp); + } + } + + /** + * Get the list of components which are actively monitored by + * this resource. + */ + public List getComponents() + { + return ((List) compList.clone()); + } + + /** + * Return the maximum number of samples this monitor will + * hold. + */ + public int getMaxSampleSize() + { + return (maxSize); + } + + /** + * Return the object which is being monitored. + */ + public Resource getMonitored() + { + return (target); + } + + /** + * Set the resource to be monitored. A resource target can + * only be set once, if you attempt to modify it then an + * IllegalArgumentException is thrown. + * + * @param target The resource to be monitored. + * @throws IllegalArgumentException if the target has already + * been set. + */ + public void setResource(Resource target) + { + if (this.target != null) + this.target = target; + else + throw new IllegalArgumentException("Once the target " + + "of a ResourceMonitor is set, it cannot be " + + "changed."); + } + + /** + * Return the name of the monitored object. + * + * @throws PoolsException if there is an error accessing the + * pool element. + */ + public String getName() throws PoolsException + { + String type = target.getStringProperty("type"); + return (target.getStringProperty(type + ".name")); + } + + /** + * Update the derived statistics. + */ + public void updateDerived() + { + StatisticList util = (StatisticList) get("utilization"); + AggregateStatistic stat = calcDerivedStatistic("utilization"); + if (stat != null) + util.add(stat); + } + + /** + * Get a derived statistic. + * + * @param name The name of the statistic to get. + */ + public AggregateStatistic getDerivedStatistic(String name) + { + return ((AggregateStatistic)((StatisticList)get(name)). + getLast()); + } + + /** + * Return the latest value of a derived statistic. + * + * @param name is the name of the derived statistic to be + * returned. + */ + private AggregateStatistic calcDerivedStatistic(String name) + { + /* + * The only statistic which can be obtained from this + * resource monitor is utilization. A utilization + * statistic actually represents a complex + * manipulation of several lower level + * statistics. This manipulation is performed here + * until a good interface can be thought through which + * best captures this abstraction. + */ + if (name.compareTo("utilization") != 0) + throw new IllegalArgumentException("No such derived " + + "statistic: " + name); + /* + * This statistic is based on lower level + * monotonically increasing numbers. The statistic can + * thus only be derived as an observation of the + * change in value over time of these values. + */ + + StatisticList first = (StatisticList) get("idle"); + + switch (first.size()) { + case 0: + case 1: + return (null); + default: + BigInteger total = new BigInteger("0"); + double utilV = 0.0; + double idleV = 0.0; + LinkedList keys = new LinkedList(keySet()); + keys.remove("utilization"); + for (int i = 0; i < keys.size(); i++) { + StatisticList sl = (StatisticList) get(keys. + get(i)); + AggregateStatistic sv1 = (AggregateStatistic) + sl.getLast(); + AggregateStatistic sv2 = (AggregateStatistic) + sl.get(sl.size() - 2); + if (sl.getName().compareTo("idle") == 0) + idleV = ((UnsignedInt64) sv1. + subtract(sv2).getValue()). + doubleValue(); + total = total.add((UnsignedInt64) sv1. + subtract(sv2).getValue()); + } + utilV = 100 * ((total.doubleValue() - idleV) / + total.doubleValue()); + return (new DoubleStatistic(new Double(utilV), + ((AggregateStatistic)first.get(first.size() - + 2)).getStart(), ((AggregateStatistic)first. + getLast()).getEnd())); + } + } + + void resetData(String name) + { + StatisticList sl = (StatisticList) get(name); + sl.clear(); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Solver.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Solver.java new file mode 100644 index 0000000000..cae0549f51 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Solver.java @@ -0,0 +1,96 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.domain.pools; + +import java.util.Set; + +import com.sun.solaris.service.pools.Configuration; +import com.sun.solaris.service.pools.Element; +import com.sun.solaris.service.pools.PoolsException; + +/** + * This interface specifies the contract between poold and the poold + * allocation algorithms. + */ + +public interface Solver { + /** + * Initialize the solver. + * + * @param conf The configuration to be manipulated. + * @throws PoolsException If the initialization fails. + */ + public void initialize(Configuration conf) throws PoolsException; + + /** + * Evaluate whether a workload based reconfiguration is + * required. + * + * @param mon The monitor to be used during examination. + * @throws PoolsException If the examination fails. + * @throws StaleMonitorException If the monitor is stale. + */ + public boolean examine(Monitor mon) throws PoolsException, + StaleMonitorException; + + /** + * Allocate resources. Return true if a change was made. + * + * @throws Exception If the solve fails. + */ + public boolean solve() throws Exception; + + /** + * Return true if all examined resources are capable of + * providing statistically valid data. + * + * If any of the monitored resources have not accumulated + * enough data to be statistically significant, then this + * monitor is not ready to be used to obtain data for all + * resources. In this case, false is returned. + * + */ + public boolean isValid(); + + /** + * Return a reference to the monitor which this solver is + * using to provide statistics about the configuration which + * is to be solved. + */ + public Monitor getMonitor(); + + /** + * Return the set of objectives associated with the supplied + * element. + * + * @param elem Retrieve objectives for this element. + */ + public Set getObjectives(Element elem); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Statistic.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Statistic.java new file mode 100644 index 0000000000..819c13266b --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/Statistic.java @@ -0,0 +1,491 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.math.BigInteger; +import java.util.Date; +import java.util.Iterator; +import java.text.*; + +import com.sun.solaris.service.pools.UnsignedInt64; + +/** + * Contains the information relating to a specific statistic for an + * object. The Statistic has no notion of the source of the data, it + * is simply a repository for holding statistical information. + */ +interface Statistic +{ + /** + * Return the start of the sample period for which the + * statistic is representative. + */ + public Date getStart(); + + /** + * Return the end of the sample period for which the + * statistic is representative. + */ + public Date getEnd(); + + /** + * Get the value of this statistic. + */ + public Object getValue(); + + /** + * Get the value of this statistic as a Long. + */ + public Long getLongValue(); + + /** + * Get the value of this statistic as a Double. + */ + public Double getDoubleValue(); + + /** + * Get the value of this statistic as a UnsignedInt64. + */ + public UnsignedInt64 getUnsignedInt64Value(); +} + +/** + * An interface for Statistics which may be aggregated. + */ +interface AggregateStatistic extends Statistic +{ + /** + * Add the supplied statistic to this. + * + * @param o The other statistic. + */ + public AggregateStatistic add(AggregateStatistic o); + + /** + * Subtract the supplied statistic from this. + * + * @param o The other statistic. + */ + public AggregateStatistic subtract(AggregateStatistic o); + + /** + * Produce the aggregate of all objects in the supplied + * iterator (which must be of the same type) whose start and + * end dates lie within the supplied ranges. If either start + * or end is null, then that bound is not applied. i.e. if no + * start date is supplied, then start checking is disabled. + * + * @param start The start date for qualification in the snapshot. + * @param end The end date for qualification in the snapshot. + * @throws IllegalArgumentException If the iterator is empty. + */ + public AggregateStatistic getSnapshotForInterval(Iterator it, + Date start, Date end) throws IllegalArgumentException; +} + +/** + * A basic Statistic implementation which makes it easy to derive + * concrete statistic types. This is an immutable class, the state is + * set when the object is constructed and cannot be later changed. + */ +abstract class AbstractStatistic implements Statistic +{ + /** + * The value of the statistic. + */ + private final Object value; + + /** + * The start of the interval during which the statistic was + * captured. + */ + private final Date start; + + /** + * The end of the interval during which the statistic was + * captured. + */ + private final Date end; + + /** + * Formatter for the sample start time, used by toString(). + */ + private static final DateFormat df = new SimpleDateFormat("kk:mm:ss"); + + /** + * Constructor. This is provided as a mechanism to allow + * inherited classes to correctly initialize their state. + * + * @param value The value of this statistic. + */ + protected AbstractStatistic(Object value) + { + this(value, null, null); + } + + /** + * Constructor. This is provided as a mechanism to allow + * inherited classes to correctly initialize their state. + * + * @param value The value of this statistic. + * @param start The start of the sample period which this + * statistic represents. + * @param end The end of the sample period which this + * statistic represents. + */ + protected AbstractStatistic(Object value, Date start, Date end) + { + this.value = value; + this.start = start; + this.end = end; + } + + /** + * Return the start of the sample period for which the + * statistic is representative. + */ + public Date getStart() + { + return (start); + } + + + /** + * Return the end of the sample period for which the + * statistic is representative. + */ + public Date getEnd() + { + return (end); + } + + /** + * Get the value of this statistic. + */ + public Object getValue() + { + return (value); + } + + public abstract Long getLongValue(); + public abstract Double getDoubleValue(); + public abstract UnsignedInt64 getUnsignedInt64Value(); + + /** + * Return the string representation of this statistic. + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + + buf.append(value); + if (start != null && end != null) { + buf.append(" from "); + buf.append(df.format(start)); + buf.append(" to "); + buf.append(df.format(end)); + } + return (buf.toString()); + } +} + +/** + * A statistic of type Double. + */ +final class DoubleStatistic extends AbstractStatistic + implements AggregateStatistic +{ + + /** + * Constructor. + * + * @param value The value of this statistic. + */ + public DoubleStatistic(Double value) + { + super(value); + } + + /** + * Constructor. + * + * @param value The value of this statistic. + * @param start The start of the interval over which this + * statistic is representative. + * @param end The end of the interval over which this + * statistic is representative. + */ + public DoubleStatistic(Double value, Date start, Date end) + { + super(value, start, end); + } + + public Double getDoubleValue() + { + return ((Double) getValue()); + } + + public Long getLongValue() + { + return (new Long(((Double) getValue()).longValue())); + } + + public UnsignedInt64 getUnsignedInt64Value() + { + return (new UnsignedInt64(Long.toString(((Double) getValue()). + longValue()))); + } + + public AggregateStatistic add(AggregateStatistic o) + { + Double v1 = getDoubleValue(); + Double v2 = o.getDoubleValue(); + + return (new DoubleStatistic(new Double(v1.doubleValue() + + v2.doubleValue()), + getStart(), getEnd())); + } + + public AggregateStatistic subtract(AggregateStatistic o) + { + Double v1 = getDoubleValue(); + Double v2 = o.getDoubleValue(); + + return (new DoubleStatistic(new Double(v1.doubleValue() - + v2.doubleValue()), + getStart(), getEnd())); + } + + public AggregateStatistic getSnapshotForInterval(Iterator it, + Date start, Date end) throws IllegalArgumentException + { + double total = 0; + int count = 0; + Date first = start, last = end; + + while (it.hasNext()) { + DoubleStatistic s = (DoubleStatistic) it.next(); + if (start != null) { + if (s.getStart().compareTo(start) < 0) + continue; + } + if (first == null) + first = s.getStart(); + if (end != null) { + if (s.getEnd().compareTo(end) > 0) + continue; + } + last = s.getEnd(); + total += s.getDoubleValue().doubleValue(); + count++; + } + if (count == 0) + throw new IllegalArgumentException("Cannot derive a " + + "snapshot from an empty iterator"); + return (new DoubleStatistic(new Double(total / count), first, + last)); + } +} + +/** + * A statistic of type Long. + */ +final class LongStatistic extends AbstractStatistic + implements AggregateStatistic +{ + + /** + * Constructor. + * + * @param value The value of this statistic. + * @param start The start of the interval over which this + * statistic is representative. + * @param end The end of the interval over which this + * statistic is representative. + */ + public LongStatistic(Long value, Date start, Date end) + { + super(value, start, end); + } + + public Double getDoubleValue() + { + return (new Double(((Long) getValue()).longValue())); + } + + public Long getLongValue() + { + return ((Long) getValue()); + } + + public UnsignedInt64 getUnsignedInt64Value() + { + return (new UnsignedInt64(Long.toString(((Long) getValue()). + longValue()))); + } + + public AggregateStatistic add(AggregateStatistic o) + { + Long v1 = getLongValue(); + Long v2 = o.getLongValue(); + + return (new LongStatistic(new Long(v1.longValue() + + v2.longValue()), + getStart(), getEnd())); + } + + public AggregateStatistic subtract(AggregateStatistic o) + { + Long v1 = getLongValue(); + Long v2 = o.getLongValue(); + + return (new LongStatistic(new Long(v1.longValue() - + v2.longValue()), + getStart(), getEnd())); + } + + public AggregateStatistic getSnapshotForInterval(Iterator it, + Date start, Date end) throws IllegalArgumentException + { + long total = 0; + int count = 0; + Date first = start, last = end; + while (it.hasNext()) { + LongStatistic s = (LongStatistic) it.next(); + if (start != null) { + if (s.getStart().compareTo(start) < 0) + continue; + } + if (first == null) + first = s.getStart(); + if (end != null) { + if (s.getEnd().compareTo(end) > 0) + continue; + } + last = s.getEnd(); + total += s.getLongValue().longValue(); + count++; + } + if (count == 0) + throw new IllegalArgumentException("Cannot derive a " + + "snapshot from an empty iterator"); + return (new LongStatistic(new Long(total / count), first, + last)); + } +} + +/** + * A statistic of type UnsignedInt64. + */ +final class UnsignedInt64Statistic extends AbstractStatistic + implements AggregateStatistic +{ + + /** + * Constructor. + * + * @param value The value of this statistic. + * @param start The start of the interval over which this + * statistic is representative. + * @param end The end of the interval over which this + * statistic is representative. + */ + public UnsignedInt64Statistic(UnsignedInt64 value, Date start, + Date end) + { + super(value, start, end); + } + + public Double getDoubleValue() + { + return (new Double(((UnsignedInt64) getValue()).longValue())); + } + + public Long getLongValue() + { + return (new Long(((UnsignedInt64) getValue()).longValue())); + } + + public UnsignedInt64 getUnsignedInt64Value() + { + return ((UnsignedInt64) getValue()); + } + + public AggregateStatistic add(AggregateStatistic o) + { + UnsignedInt64 v1 = getUnsignedInt64Value(); + UnsignedInt64 v2 = o.getUnsignedInt64Value(); + + return (new UnsignedInt64Statistic( + new UnsignedInt64(v1.add(v2)), + getStart(), getEnd())); + } + + public AggregateStatistic subtract(AggregateStatistic o) + { + UnsignedInt64 v1 = getUnsignedInt64Value(); + UnsignedInt64 v2 = o.getUnsignedInt64Value(); + + return (new UnsignedInt64Statistic( + new UnsignedInt64(v1.subtract(v2)), + getStart(), getEnd())); + } + + public AggregateStatistic getSnapshotForInterval(Iterator it, + Date start, Date end) throws IllegalArgumentException + { + BigInteger total = new BigInteger("0"); + int count = 0; + Date first = start, last = end; + while (it.hasNext()) { + UnsignedInt64Statistic s = (UnsignedInt64Statistic) + it.next(); + if (start != null) { + if (s.getStart().compareTo(start) < 0) + continue; + } + if (first == null) + first = s.getStart(); + + if (end != null) { + if (s.getEnd().compareTo(end) > 0) + continue; + } + last = s.getEnd(); + total = total.add(s.getUnsignedInt64Value()); + count++; + } + if (count == 0) + throw new IllegalArgumentException("Cannot derive a " + + "snapshot from an empty iterator"); + return (new UnsignedInt64Statistic( + new UnsignedInt64(total.divide(new BigInteger( + Integer.toString(count)))), first, last)); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/StatisticList.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/StatisticList.java new file mode 100644 index 0000000000..64dcb8ed45 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/StatisticList.java @@ -0,0 +1,737 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + + +import java.util.*; +import java.text.DecimalFormat; + +import com.sun.solaris.service.logging.*; + +/** + * Contains information about statistics. An instance must only + * contain Statistics of the same type. + */ +class StatisticList extends LinkedList +{ + /** + * The name of the statistic. + */ + private final String name; + + /** + * The maximum number of samples to be stored. + */ + private final int maxSize; + + /** + * The list of StatisticListeners. + */ + private List listeners; + + /** + * Statistically assess utilization. + */ + private StatisticOperations statisticOperations; + + /** + * Constructor. + */ + public StatisticList() + { + this("default", 10); + } + + /** + * Constructor. Statistics will not be held for this set. + * + * @param name is the name of the contained statistics + * @param size is the maximum number of statistics to hold + */ + public StatisticList(String name, int size) + { + this(name, size, false); + } + + /** + * Constructor. + * + * @param name is the name of the contained statistics + * @param size is the maximum number of statistics to hold + * @param doStats indicates whether or not statistics should + * be calculated for the data. + */ + public StatisticList(String name, int size, boolean doStats) + throws IllegalArgumentException + { + super(); + this.name = name; + if (size < 1) + throw new IllegalArgumentException("Size must be > 0"); + this.maxSize = size; + listeners = new LinkedList(); + if (doStats) { + statisticOperations = new StatisticOperations(this); + addStatisticListener(statisticOperations); + } + } + + /** + * Return the name of the Statistics being sampled. + */ + public String getName() + { + return (name); + } + + /** + * Return a "snapshot" which is the aggregation of all + * statistic records. + * + * @throws NoSuchElementException if there is an error + * accessing a list member. + */ + public AggregateStatistic getSnapshot() + throws NoSuchElementException + { + return (getSnapshotForInterval(iterator(), null, null)); + } + + /** + * Return a "snapshot" of the data using the supplied + * iterator. + * + * @param it An iterator over the contained elements to be + * used as the basis for the snapshot. + * @throws NoSuchElementException if there is an error + * accessing a list member. + */ + private AggregateStatistic getSnapshot(Iterator it) + throws NoSuchElementException + { + return (getSnapshotForInterval(it, null, null)); + } + + /** + * Returns the aggregated value for the StatisticList only + * including samples which satisfy the start and end criteria. + * + * @param start start time or null if unspecified. + * @param end end time or null if unspecified. + * @throws NoSuchElementException if there is an error + * accessing a list member. + */ + public AggregateStatistic getSnapshotForInterval(Date start, + Date end) throws NoSuchElementException + + { + return (getSnapshotForInterval(iterator(), start, end)); + } + + /** + * Returns the aggregated value for the StatisticList only + * including samples which satisfy the start and end criteria. + * + * @param it An iterator over the contained elements to be + * used as the basis for the snapshot. + * @param start start time or null if unspecified. + * @param end end time or null if unspecified. + * @throws NoSuchElementException if there is an error + * accessing a list member. + */ + private AggregateStatistic getSnapshotForInterval(Iterator it, + Date start, Date end) + { + AggregateStatistic f = (AggregateStatistic) getFirst(); + return (f.getSnapshotForInterval(it, start, end)); + } + + /** + * Add the supplied object to the list. If the list is full, + * remove the first entry before adding the new entry. + * + * @param o Object to add to the list. + */ + public boolean add(Object o) + { + boolean ret; + if (size() == maxSize) + removeFirst(); + ret = super.add(o); + if (ret) + notifyStatisticAdd((AggregateStatistic) o); + return (ret); + } + + /** + * Remove the supplied object from the list. + * + * @param o Object to remove from the list. + */ + public boolean remove(Object o) + { + boolean ret; + ret = super.remove(o); + if (ret) + notifyStatisticRemove((AggregateStatistic) o); + return (ret); + } + + /** + * Removes and returns the first element from this list. + * + * @return the first element from this list. + * @throws NoSuchElementException if this list is empty. + */ + public Object removeFirst() { + Object first = getFirst(); + remove(first); + return (first); + } + + /** + * Add a listener for StatisticEvents. + * + * @param l Listener to add. + */ + public void addStatisticListener(StatisticListener l) { + listeners.add(l); + } + + /** + * Remove a listener for StatisticEvents. + * + * @param l Listener to remove. + */ + public void removeStatisticListener(StatisticListener l) { + listeners.remove(l); + } + + /** + * Notify all StatisticEvent listeners of a new Add event. + * + * @param s Event payload. + */ + private void notifyStatisticAdd(AggregateStatistic s) + { + StatisticEvent e = new StatisticEvent(this, + StatisticEvent.ADD, s); + + Iterator listIt = listeners.iterator(); + + while (listIt.hasNext()) { + + StatisticListener l = (StatisticListener)listIt.next(); + l.onStatisticAdd(e); + } + } + + /** + * Notify all StatisticEvent listeners of a new Remove event. + * + * @param s Event payload. + */ + private void notifyStatisticRemove(AggregateStatistic s) + { + StatisticEvent e = new StatisticEvent(this, + StatisticEvent.REMOVE, s); + + Iterator listIt = listeners.iterator(); + + while (listIt.hasNext()) { + + StatisticListener l = (StatisticListener)listIt.next(); + l.onStatisticRemove(e); + } + } + + /** + * Return true if the contents of the instance are + * statistically valid. + */ + boolean isValid() + { + return (statisticOperations.isValid()); + } + + /** + * Return the zone of control to which the supplied val + * belongs based on the target details in the supplied + * objective expression. + * + * @param kve Objective expression used to determine zone + * details. + * @param val The value to be assessed. + */ + int getZone(KVOpExpression kve, double val) + { + return (statisticOperations.getZone(kve, val)); + } + + /** + * Return the zone of control to which the supplied val + * belongs based on the mean of the sampled data. + * + * @param val The value to be assessed. + */ + int getZoneMean(double val) + { + return (statisticOperations.getZoneMean(val)); + } + + /** + * Return the difference (gap) between the target utilization + * expressed in the supplied objective expression and the + * supplied value. + * + * @param kve Objective expression used to determine target + * utilization details. + * @param val The value to be assessed. + */ + double getGap(KVOpExpression kve, double val) + { + return (statisticOperations.getGap(kve, val)); + } + + /** + * Clear all the data from the StatisticList and reset all the + * statistic counters. + */ + public void clear() + { + if (statisticOperations != null) { + removeStatisticListener(statisticOperations); + statisticOperations = new StatisticOperations(this); + addStatisticListener(statisticOperations); + } + super.clear(); + } + + /** + * Return a string which describes the zones for this set of + * data. + * + * @param kve The expression containing objectives. + * @param val The value to be assessed against objectives. + */ + public String toZoneString(KVOpExpression kve, double val) + { + return (statisticOperations.toZoneString(kve, val)); + } +} + +/** + * Event class which describes modifications (Add, Remove) to a + * StatisticList instance. + */ +final class StatisticEvent extends EventObject +{ + /** + * Identifier for an ADD event. + */ + public static final int ADD = 0x1; + + /** + * Identifier for a REMOVE event. + */ + public static final int REMOVE = 0x2; + + /** + * The target of the event. + */ + private final AggregateStatistic target; + + /** + * The identifier of this event. + */ + private final int id; + + /** + * Constructor. + * + * @param source The source of the event. + * @param id The type of the event. + * @param target The target of the event. + */ + public StatisticEvent(Object source, int id, AggregateStatistic target) + { + super(source); + this.id = id; + this.target = target; + } + + /** + * Return the target of the event. + */ + public AggregateStatistic getTarget() + { + return (target); + } + + /** + * Return the ID (type) of the event. + */ + public int getID() + { + return (id); + } + + /** + * Return the source of the event. This is a typesafe + * alternative to using getSource(). + */ + public StatisticList getStatisticList() + { + return ((StatisticList) source); + } + +} + +/** + * The listener interface for receiving statistic events. The class + * that is interested in processing a statistic event implements this + * interface, and the object created with that class is registered + * with a component, using the component's addStatisticListener + * method. When the statistic event occurs, the relevant method in the + * listener object is invoked, and the StatisticEvent is passed to it. + */ +interface StatisticListener extends EventListener +{ + /** + * Invoked when a statistic is added to the source + * StatisticList. + * + * @param e The event. + */ + public void onStatisticAdd(StatisticEvent e); + + /** + * Invoked when a statistic is removed from the source + * StatisticList. + * + * @param e The event. + */ + public void onStatisticRemove(StatisticEvent e); +} + +/** + * This class performs statistical calculations on a source + * StatisticList. Zones are regions in a set of samples which are set + * to be at 1, 2 and 3 standard deviations from the mean. ZONEC is + * closest to the center, with ZONEZ representing the region beyond + * ZONEA. + */ +class StatisticOperations implements StatisticListener +{ + /** + * Control zone C. + */ + public static final int ZONEC = 0x00010; + + /** + * Control zone B. + */ + public static final int ZONEB = 0x00100; + + /** + * Control zone A. + */ + public static final int ZONEA = 0x01000; + + /** + * Control zone Z. + */ + public static final int ZONEZ = 0x10000; + + /** + * Direction from mean (used to test ZONELT and ZONEGT). + */ + public static final int ZONET = 0x00001; + + /** + * Less than the mean. + */ + public static final int ZONELT = 0x00000; + + /** + * Greater than the mean. + */ + public static final int ZONEGT = 0x00001; + + /** + * The raw statistical data. + */ + private final StatisticList statistics; + + /** + * The mean of the samples. + */ + private double mean; + + /** + * The standard deviation of the samples. + */ + private double sd; + + /** + * The total of the samples. + */ + private AggregateStatistic total; + + /** + * Constructs a new StatisticOperations object for working on + * the given statistic, whose values are in the given + * (modifiable) data set. + * + * @param statistics The statistics to operate on. + */ + public StatisticOperations(StatisticList statistics) + { + this.statistics = statistics; + total = new DoubleStatistic(new Double(0.0)); + } + + /** + * Calculate the standard deviation for the data held in the + * associated StatisticsList. + */ + private void calc_sd() + { + Iterator it; + + sd = 0; + it = statistics.iterator(); + while (it.hasNext()) { + Double val = (Double)((DoubleStatistic) + ((AggregateStatistic)it.next())).getValue(); + + sd += java.lang.Math.pow(val.doubleValue() - mean, 2); + } + sd /= statistics.size(); + sd = java.lang.Math.sqrt(sd); + } + + /** + * Return a string which describes the zones for this set of + * data. + * + * @param kve The expression containing objectives. + * @param val The value to be assessed against objectives. + */ + public String toZoneString(KVOpExpression kve, double val) + { + if (isValid()) { + DecimalFormat f = new DecimalFormat("00.00"); + double target = kve.getValue(); + + if (kve.getOp() == KVOpExpression.LT) { + target -= 3 * sd; + } else if (kve.getOp() == KVOpExpression.GT) { + target += 3 * sd; + } + StringBuffer buf = new StringBuffer(); + buf.append(kve.toString()); + buf.append("\nsample = " + statistics.size()); + buf.append("\n\ttarget: " + f.format(target)); + buf.append("\n\tvalue: " + f.format(val)); + buf.append("\n\tsd: " + f.format(sd)); + buf.append("\n\tZones:"); + buf.append("\n\t\tC:" + f.format(target - sd)); + buf.append("-" + f.format(target + sd)); + buf.append("\n\t\tB:" + f.format(target - 2 * sd)); + buf.append("-" + f.format(target + 2 * sd)); + buf.append("\n\t\tA:" + f.format(target - 3 * sd)); + buf.append("-" + f.format(target + 3 * sd)); + return (buf.toString()); + } else { + return ("Still sampling..."); + } + } + + + /** + * Return a string which describes this instance. + */ + public String toString() + { + DecimalFormat f = new DecimalFormat("00.00"); + + if (isValid()) { + return ("sample = " + statistics.size() + + "\n\tmean: " + f.format(mean) + + "\n\tsd: " + f.format(sd) + + "\n\tZones:" + + "\n\t\tC:" + f.format(mean - sd) + + "-" + f.format(mean + sd) + + "\n\t\tB:" + f.format(mean - 2 * sd) + + "-" + f.format(mean + 2 * sd) + + "\n\t\tA:" + f.format(mean - 3 * sd) + + "-" + f.format(mean + 3 * sd)); + } else { + return ("Still sampling..."); + } + } + + /** + * Return true if the data is normally distributed. This + * method currently just returns true if the sample size is >= + * 5. It could be extended to use a test of normality, for + * instance "Pearson's Chi-Squared Test" or "Shapiro-Wilks W + * Test". + */ + public boolean isValid() + { + if (statistics.size() >= 5) + return (true); + return (false); + } + + /** + * Calculate the statistical values for the associated + * samples. This method should be called when the sample + * population changes. + */ + private final void process() + { + mean = ((Double)((DoubleStatistic)total).getValue()). + doubleValue() / statistics.size(); + calc_sd(); + } + + /** + * Return the control zone for the supplied value using the + * information derived from the monitored statistics and the + * objective expressed in the supplied objective expression. + * + * @param kve The target utilization expression. + * @param val The value to be evaluated. + */ + public int getZone(KVOpExpression kve, double val) + { + if (!isValid()) + return (StatisticOperations.ZONEC); + + double target = kve.getValue(); + + if (kve.getOp() == KVOpExpression.LT) { + target -= 3 * sd; + } else if (kve.getOp() == KVOpExpression.GT) { + target += 3 * sd; + } + + return (getZone(target, val)); + } + + /** + * Return the control zone for the supplied value using the + * information derived from the monitored statistics. + * + * @param val The value to be evaluated. + */ + public int getZoneMean(double val) + { + if (!isValid()) + return (StatisticOperations.ZONEC); + + return (getZone(mean, val)); + } + + /** + * Return the control zone for the supplied value using the + * information derived from the supplied target. + * + * @param val The value to be evaluated. + */ + private int getZone(double target, double val) + { + if (!isValid()) + return (StatisticOperations.ZONEC); + + return ((val < target - 3 * sd) ? + ZONEZ | ZONELT : (val > target + 3 * sd) ? + ZONEZ | ZONEGT : (val < target - 2 * sd) ? + ZONEA | ZONELT : (val > target + 2 * sd) ? + ZONEA | ZONEGT : (val < target - sd) ? + ZONEB | ZONELT : (val > target + sd) ? + ZONEB | ZONEGT : (val < target) ? + ZONEC | ZONELT : ZONEC | ZONEGT); + } + + /** + * Return the difference (gap) between the target utilization + * expressed in the supplied objective expression and the + * supplied value. + * + * @param kve Objective expression used to determine target + * utilization details. + * @param val The value to be assessed. + */ + public double getGap(KVOpExpression kve, double val) + { + if (!isValid()) + return (0.0); + + double target = kve.getValue(); + + if (kve.getOp() == KVOpExpression.LT) { + target -= 3 * sd; + } else if (kve.getOp() == KVOpExpression.GT) { + target += 3 * sd; + } + if (val - target < -100) + return (-100); + else if (val - target > 100) + return (100); + else + return (val - target); + } + + /** + * Event handler for added statistics. + * + * @param e The event. + */ + public void onStatisticAdd(StatisticEvent e) + { + total = total.add(e.getTarget()); + process(); + + } + + /** + * Event handler for removed statistics. + * + * @param e The event. + */ + public void onStatisticRemove(StatisticEvent e) + { + total = total.subtract(e.getTarget()); + process(); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/SystemMonitor.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/SystemMonitor.java new file mode 100644 index 0000000000..b458d56e45 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/SystemMonitor.java @@ -0,0 +1,366 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.util.*; +import java.util.logging.*; + +import com.sun.solaris.service.kstat.*; +import com.sun.solaris.service.logging.Severity; +import com.sun.solaris.domain.pools.*; +import com.sun.solaris.service.pools.*; +import com.sun.solaris.service.timer.*; + +/** + * Regularly samples the objective-related utilization statistics of + * the resource in the pool with the given configuration. + */ +class SystemMonitor implements Monitor +{ + /** + * The pool configuration with resources to be monitored. + */ + private Configuration conf; + + /** + * The map of monitored resources.The map is keyed by + * resource, with the values being the monitorable instances. + */ + private Map monitored; + + /** + * Default sample interval (milliseconds). + */ + public static final int DEF_SAMPLE_INT = 15000; + + /** + * Sample interval (milliseconds, default 15000). + */ + private int interval; + + /** + * Sample interval property name. + */ + static final String SAMPLE_INTERVAL_PROP_NAME = + "system.poold.monitor-interval"; + + /** + * Kstat interface for raw data + */ + private KstatCtl kc; + + /** + * Raw statistics which are sampled each interval. + */ + private final String stats[] = { "idle", "kernel", "wait", "user" }; + + /** + * Timer regulating sampling frequency. + */ + private RecurringEventTimer timer; + + /** + * The number of samples taken. + */ + private int sampleCount = 0; + + /** + * Time the last sample was taken. + */ + private Date lastSampleTime = null; + + /** + * Constructs a new monitor which is not associated with a + * specific configuration. + */ + public SystemMonitor() + { + this(null); + } + + /** + * Constructs a new Monitor for monitoring the resources in the + * given configuration using the given statistic source. + * + * @param conf The configuration which is monitored. + */ + public SystemMonitor(Configuration conf) + { + this.conf = conf; + monitored = new HashMap(); + kc = new KstatCtl(); + } + + /** + * Initialize the monitor with the configuration which is to + * be monitored. + * + * @param conf The configuration which is monitored. + * + * @throws PoolsException if manipulating the configuration + * fails. + * @throws StaleMonitorException if the resource monitors + * cannot be set. + */ + public void initialize(Configuration conf) throws PoolsException, + StaleMonitorException + { + Poold.CONF_LOG.log(Severity.DEBUG, "initializing"); + this.conf = conf; + try { + kc.chainUpdate(); + } catch (KstatChainUpdateException kcue) { + Poold.utility.die(Poold.CONF_LOG, kcue); + } + + try { + interval = (int)conf.getLongProperty( + SAMPLE_INTERVAL_PROP_NAME); + } catch (PoolsException pe) { + interval = DEF_SAMPLE_INT; + } + timer = new SimpleRecurringEventTimer(interval); + + setResourceMonitors("pset"); + } + + /** + * Add all resources of the supplied type in the monitored + * configuration to the set of monitored resources. Remove + * redundant monitors for resources which no longer exist. + * Don't monitor resource sets which are empty. + * + * @param type The type of the resources to be added + */ + private void setResourceMonitors(String type) throws PoolsException, + StaleMonitorException + { + Value val = new Value("type", type); + + List valueList = new LinkedList(); + valueList.add(val); + Iterator resIt = conf.getResources(valueList).iterator(); + val.close(); + HashSet oldKeys = new HashSet(monitored.keySet()); + while (resIt.hasNext()) { + Resource res = (Resource)resIt.next(); + ResourceMonitor mon = null; + boolean activeComponents = false; + + List compList = res.getComponents(null); + Iterator compIt = compList.iterator(); + while (compIt.hasNext()) { + Component comp = (Component) compIt.next(); + String status = comp.getStringProperty( + "cpu.status"); + if (status.compareTo("off-line") != 0 && + status.compareTo("powered-off") != 0) { + activeComponents = true; + break; + } + } + if (activeComponents == false) + continue; + + if (monitored.containsKey(res)) { + mon = get(res); + for (int i = 0; i < stats.length; i++) + mon.resetData(stats[i]); + } else { + mon = new ResourceMonitor(res, 50); + for (int i = 0; i < stats.length; i++) { + StatisticList sl = new StatisticList( + stats[i], 2); + mon.put(stats[i], sl); + } + mon.put("utilization", new StatisticList( + "utilization", mon.getMaxSampleSize(), + true)); + monitored.put(res, mon); + } + mon.initialize(); + oldKeys.remove(res); + } + monitored.keySet().removeAll(oldKeys); + } + + /** + * Get the next sample. Before obtaining the sample, the call + * will block for the interval which was specified when this + * monitor was initialized. + * + * @throws StaleMonitorException if a statistic cannot be obtained. + * @throws PoolsException if there is an error manipulating the + * pools configuration. + * @throws InterruptedException if the thread is interrupted + * while waiting for the sampling time to arrive. The caller + * may wish to check other conditions before possibly + * reinitiating the sample. + */ + public void getNext() throws StaleMonitorException, PoolsException, + InterruptedException + { + Poold.MON_LOG.log(Severity.DEBUG, "waiting sampling interval"); + + Date start = lastSampleTime; + if (start == null) + start = new Date(); + + timer.waitUntilNextFiring(); + Date end = new Date(); + + Poold.MON_LOG.log(Severity.DEBUG, "sampling"); + Iterator itMon = monitored.values().iterator(); + while (itMon.hasNext()) { + ResourceMonitor mon = (ResourceMonitor) itMon.next(); + List compList = mon.getComponents(); + Iterator itComp = compList.iterator(); + BigInteger statsv[] = new BigInteger[4]; + while (itComp.hasNext()) { + Component cpu = (Component) itComp.next(); + Kstat kstat = kc.lookup("cpu", + (int) cpu.getLongProperty("cpu.sys_id"), + "sys"); + if (kstat == null) + throw new StaleMonitorException(); + UnsignedInt64 value; + try { + kstat.read(); + for (int i = 0; i < stats.length; i++) { + value = (UnsignedInt64) kstat. + getValue("cpu_ticks_" + + stats[i]); + if (value == null) + throw new + StaleMonitorException(); + if (statsv[i] == null) + statsv[i] = value; + else + statsv[i] = statsv[i]. + add(value); + } + } catch (KstatException ke) { + StaleMonitorException sme = + new StaleMonitorException(); + sme.initCause(ke); + Poold.MON_LOG.log(Severity.DEBUG, + "configuration necessary due to " + + ke); + throw(sme); + } + } + if (compList.isEmpty() == false) { + for (int i = 0; i < stats.length; i++) { + StatisticList sl; + sl = (StatisticList) mon.get(stats[i]); + sl.add(new UnsignedInt64Statistic( + new UnsignedInt64(statsv[i]. + divide(new BigInteger( + Integer.toString( + compList.size())))), + start, end)); + } + } + mon.updateDerived(); + } + + sampleCount++; + lastSampleTime = end; + } + + /** + * Return the number of samples taken. This is the number of + * successful calls to <code>getNext()</code>. + */ + public int getSampleCount() + { + return (sampleCount); + } + + /** + * Return the utilization of the supplied resource. The + * utilization is represented as a percentage between 0 + * and 100. + * + * @param res A reference to a configuration resource. + */ + public double getUtilization(Resource res) throws StaleMonitorException + { + ResourceMonitor mon = get(res); + DoubleStatistic util = null; + try { + util = (DoubleStatistic)mon.getDerivedStatistic( + "utilization"); + } catch (NoSuchElementException nsee) { + util = new DoubleStatistic(new Double(0)); + } + Poold.MON_LOG.log(Severity.DEBUG, + res + " utilization " + util.toString()); + return (((Double)util.getValue()).doubleValue()); + } + + /** + * Return true if the system contains enough sampled data for + * monitoring to be worthwhile. + */ + public boolean isValid() + { + Iterator itMon = monitored.values().iterator(); + while (itMon.hasNext()) { + ResourceMonitor mon = (ResourceMonitor) itMon.next(); + + Iterator itSL = mon.values().iterator(); + while (itSL.hasNext()) { + StatisticList sl = (StatisticList) itSL.next(); + if (sl.getName().compareTo("utilization") == + 0) { + if (sl.isValid() == false) + return (false); + } + } + } + return (true); + } + + /** + * Return the ResourceMonitor for the supplied Resource + * + * @throws StaleMonitorException if the ResourceMonitor cannot be found. + */ + public ResourceMonitor get(Resource res) throws StaleMonitorException + { + ResourceMonitor rm = (ResourceMonitor)monitored.get(res); + + if (rm == null) + throw new StaleMonitorException(); + return (rm); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/SystemSolver.java b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/SystemSolver.java new file mode 100644 index 0000000000..51b37aa5a6 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/SystemSolver.java @@ -0,0 +1,986 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.domain.pools; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.*; +import java.util.regex.*; +import java.text.DecimalFormat; + +import com.sun.solaris.service.locality.*; +import com.sun.solaris.service.logging.*; +import com.sun.solaris.service.pools.*; +import com.sun.solaris.service.exception.*; + +/** + * The <code>SystemSolver</code> class implements a dynamic resource + * allocation solver. The Solver takes a configuration and "solves" + * the resource allocation problem. + * + * This class operates upon a configuration which is suppplied during + * initialization. Its responsibilities include: + * <ul> + * <li><p> + * Maintaining decision history + * <li><p> + * Maintaining information about the locality domain + * <li><p> + * Maintaining a map of all elements and their associated set of objectives + * <li><p> + * Identifying objective expressions with a configuration + * </ul> + */ +class SystemSolver implements Solver { + /** + * The default location of this history file. + */ + public static final String DH_FILE_DEF_PATH = + "/var/adm/pool/history"; + + /** + * The property overriding the default decision history path. + */ + public static final String DH_FILE_PROP_NAME = + "system.poold.history-file"; + + /** + * The LocalityDomain extracted from the configuration. + */ + private LocalityDomain ldom; + + /** + * The objective map used to link all elements with their set + * of objectives. + */ + private Map objMap; + + /** + * The pattern used to identify objective expressions. + */ + private static final Pattern p0 = Pattern.compile(";"); + + /** + * The configuration for which this solver is "solving". + */ + private Configuration conf; + + /** + * Monitor providing statistics for this solver. + */ + private final Monitor monitor; + + /** + * The decision history maintainer. + */ + private DecisionHistory dh; + + /** + * The path to the decision history file. + */ + private String dhPath; + + /** + * The number of CPUs on the system. + */ + private int cpuCount; + + /** + * The number of locality triggered examinations made. + */ + private int examineCount; + + /** + * Constructs a solver which initialises a decision history + * maintainer. The decision history is be used during operation + * to veto historically-poor decisions output from the objective + * function. + */ + SystemSolver(Monitor monitor) + { + /* + * Create a HashMap to store all objectives. + */ + objMap = new HashMap(); + this.monitor = monitor; + } + + /** + * Initialize the solver for operation upon the supplied + * configuration. Possible objective expressions set upon + * target elements are identified and stored in an objective + * map which associates elements with the set of their + * objectives. + * + * @param conf The configuration to be manipulated. + * @throws PoolsException If the initialization fails. + */ + public void initialize(Configuration conf) throws PoolsException + { + String oString = null; + String exps[]; + + this.conf = conf; + /* + * Count the CPUs in the system, this is used to + * control locality objective processing in the + * examine() method. + */ + cpuCount = conf.getComponents(null).size(); + examineCount = 0; + /* + * Remove any old objectives + */ + objMap.clear(); + + /* + * Extract any configuration objectives + */ + try { + oString = conf.getStringProperty( + "system.poold.objectives"); + if (oString.length() > 0) { + Set oSet = new HashSet(); + objMap.put(conf, oSet); + Poold.CONF_LOG.log(Severity.DEBUG, + "adding configuration objective " + + oString); + exps = p0.split(oString); + for (int i = 0; i < exps.length; i++) { + try { + Expression exp = + Expression.valueOf( + exps[i]); + addObjective(oSet, "system", + exp); + } catch (IllegalArgumentException iae) { + Poold.utility.warn( + Poold.CONF_LOG, iae, false); + } + } + } + } catch (PoolsException pe) { + /* + * Ignore as this means there is no objective + * property + */ + } + /* + * Now extract all pset objectives + */ + Value typeProp = new Value("type", "pset"); + List valueList = new LinkedList(); + valueList.add(typeProp); + Iterator resIt = conf.getResources(valueList).iterator(); + typeProp.close(); + while (resIt.hasNext()) { + Resource resource = (Resource)resIt.next(); + + try { + oString = resource.getStringProperty( + "pset.poold.objectives"); + if (oString.length() > 0) { + Set oSet = new HashSet(); + objMap.put(resource, oSet); + Poold.CONF_LOG.log(Severity.DEBUG, + "adding " + + resource.getStringProperty( + "pset.name") + + " objective \"" + oString + "\""); + exps = p0.split(oString); + for (int i = 0; i < exps.length; i++) { + Expression exp = null; + try { + exp = Expression. + valueOf(exps[i]); + addObjective(oSet, + "pset", exp); + } catch + (IllegalArgumentException e) + { + Poold.utility.warn( + Poold.CONF_LOG, e, + false); + } + } + } + } catch (PoolsException pe) { + continue; + } + } + Poold.CONF_LOG.log(Severity.DEBUG, "objective map: " + + objMap.toString()); + + /* + * Capture the LocalityDomain details. + */ + if (ldom != null) { + ldom.close(); + } + try { + ldom = new LocalityDomain(LocalityDomain.LGRP_VIEW_OS); + } catch (Exception e) { + Poold.utility.die(Poold.OPT_LOG, e); + } + + /* + * Load or create the decision history. + */ + String newDhPath; + try { + newDhPath = conf.getStringProperty( + DH_FILE_PROP_NAME); + } catch (PoolsException pe) { + newDhPath = DH_FILE_DEF_PATH; + } + + if (!newDhPath.equals(dhPath)) { + try { + dh = DecisionHistory.loadFromFile(newDhPath); + Poold.CONF_LOG.log(Severity.DEBUG, + "loaded history file " + newDhPath); + } catch (Exception e) { + if (!(e instanceof FileNotFoundException)) { + Poold.CONF_LOG.log(Severity.WARNING, + newDhPath + + ": contents unusable; ignoring"); + Poold.CONF_LOG.log(Severity.DEBUG, + newDhPath + ": contents unusable", + e); + } + /* + * Use current DecisionHistory instead, + * if any. + */ + if (dh == null) + dh = new DecisionHistory(); + } + + /* + * Try using the new path. + */ + try { + dh.syncToFile(newDhPath); + } catch (Exception e) { + Poold.utility.die(Poold.CONF_LOG, + new PooldException(newDhPath + + ": couldn't synchronize history file") + .initCause(e), false); + } + dhPath = newDhPath; + } + } + + /** + * Determine if the given resource has non-workload-dependent + * objectives. + * @param elem The element to examine. + */ + private boolean hasNonWorkloadDependentObjectives(Element elem) + { + Set elemObj = (Set)objMap.get(elem); + + /* + * This code relies upon the fact that an element with + * no objectives will not have an empty set, but rather + * no value in the objMap. + */ + + if (elemObj == null) + return (false); + + Iterator elemObjIt = elemObj.iterator(); + while (elemObjIt.hasNext()) + if (elemObjIt.next() instanceof + WorkloadDependentObjective) + return (false); + + return (true); + } + + /** + * Determine if the given resource has workload-dependent + * objectives. + * @param elem The element to examine. + */ + private boolean hasWorkloadDependentObjectives(Element elem) + { + Set elemObj = (Set)objMap.get(elem); + + /* + * This code relies upon the fact that an element with + * no objectives will not have an empty set, but rather + * no value in the objMap. + */ + + if (elemObj == null) + return (false); + + Iterator elemObjIt = elemObj.iterator(); + while (elemObjIt.hasNext()) + if (elemObjIt.next() instanceof + WorkloadDependentObjective) + return (true); + + return (false); + } + + /** + * Return true if the monitored configuration should be + * reconfigured. All workload-dependent objectives are + * examined to determine if the configuration is still + * satisfying all specified objectives on all elements. If any + * objectives are failing, then this method will return true. + * + * @param mon The monitoring object used to assess objective + * compliance. + */ + public boolean examine(Monitor mon) throws PoolsException, + StaleMonitorException + { + /* + * Take advantage of the guaranteed-valid monitor data + * for measuring the improvement of any past decisions. + */ + dh.expireAndMeasureImprovements(mon); + + Iterator objIt = objMap.keySet().iterator(); + boolean ret = false; + boolean hasLocalityObjectives = false; + boolean isMonitorValid = true; + + /* + * All objectives are examined, even though failure + * could be detected earlier. This is because logging + * of all objectives is required and the information + * about failure can be stored and used during + * solving. + */ + while (objIt.hasNext()) { + Element elem = (Element) objIt.next(); + Set elemObj = (Set) objMap.get(elem); + Iterator elemObjIt = elemObj.iterator(); + while (elemObjIt.hasNext()) { + Objective obj = (Objective) elemObjIt.next(); + Poold.OPT_LOG.log(Severity.DEBUG, + "checking objective " + obj); + if (obj instanceof WorkloadDependentObjective) { + if (isValid()) { + /* + * If any objectives + * are violated, then + * we must + * reconfigure, so + * check them all in + * turn. + */ + ret = ((WorkloadDependentObjective) + obj).examine(conf, this, elem) || + ret; + } else + isMonitorValid = false; + } + } + + /* + * Check if this is the first element, seen in + * this pass, that has locality objectives. + */ + if (!hasLocalityObjectives && + hasNonWorkloadDependentObjectives(elem)) + hasLocalityObjectives = true; + } + if (isMonitorValid == false) { + Poold.MON_LOG.log(Severity.INFO, + "not evaluating workload-dependent objectives " + + "until sufficient statistics are collected"); + } + /* + * If we don't have locality objectives, we don't force + * the reexamination. This is controlled by + * hasLocalityObjectives. + * + * So that we don't continually trigger + * reconfiguration examinations for locality + * objectives we stop forcing recalculations when we + * reach cpuCount / 2. This should be enough moves to + * get good locality for those configurations which + * have no WorkloadDependentObjectives. + */ + return (ret || (hasLocalityObjectives && (examineCount++ < + cpuCount / 2))); + } + + /** + * Reallocate resources in a configuration to achieve user + * specified objectives. Return true if the configuration has + * been updated, false otherwise. + * + * This method should only be invoked if a previous + * examination of the configuration which is monitored + * indicates that objectives are failing. The monitored + * configuration is re-opened for editing, locking that + * configuration for the duration of this operation. + * + * @throws Exception If the solve fails. + */ + public boolean solve() throws Exception + { + boolean madeMove = false; + /* + * All solving operations must be done in an + * "editable" context, so create a new modifiable + * configuration which is at the same location as the + * monitored configuration + */ + Configuration rwConf = new Configuration(conf.getLocation(), + PoolInternal.PO_RDWR); + + try { + /* + * Build a resource set importance map for use + * when propagating pool importance to each + * possible solution. Use the same logic as + * libpool and let a resource take the highest + * importance value from all pools associated + * with the set. + */ + Map resImp = new HashMap(); + List poolList = rwConf.getPools(null); + Iterator itPool = poolList.iterator(); + while (itPool.hasNext()) { + Pool pool = (Pool) itPool.next(); + long newImp = pool. + getLongProperty("pool.importance"); + List resList = pool.getResources(null); + Iterator itRes = resList.iterator(); + while (itRes.hasNext()) { + Resource res = (Resource) itRes.next(); + if (resImp.containsKey(res)) { + Long imp = (Long) resImp. + get(res); + if (newImp > imp.longValue()) + resImp.put(res, + new Long(newImp)); + } else + resImp.put(res, + new Long(newImp)); + } + } + /* + * Consider all possible alternative + * configurations. This list is generated as a + * series of moves. Administrative constraints + * are applied to the moves to prune the list of + * possible configurations. + */ + Value val = new Value("type", "pset"); + List valueList = new LinkedList(); + valueList.add(val); + + + List resList = rwConf.getResources(valueList); + val.close(); + List donors = getDonors(resList); + List receivers = getRecipients(resList); + Poold.OPT_LOG.log(Severity.DEBUG, "donors: " + + donors); + Poold.OPT_LOG.log(Severity.DEBUG, "receivers: " + + receivers); + Iterator itDonor = donors.iterator(); + List moves = new ArrayList(); + while (itDonor.hasNext()) { + Resource donor = (Resource) itDonor.next(); + List processors = getProcessors(donor); + Poold.OPT_LOG.log(Severity.DEBUG, + "donor processors: " + processors); + Iterator itProcessor = processors.iterator(); + while (itProcessor.hasNext()) { + Component cpu = (Component) itProcessor. + next(); + Iterator itReceiver = receivers. + iterator(); + while (itReceiver.hasNext()) { + Resource receiver = + (Resource) itReceiver. + next(); + /* + * Can't move to yourself + */ + if (receiver == donor) + continue; + moves.add(new ComponentMove( + donor, receiver, cpu)); + } + } + } + Poold.OPT_LOG.log(Severity.DEBUG, + "potential moves: " + moves); + /* + * Now that we have our alternative configurations, + * score each configuration by applying all objectives + * to each configuration. Hold the scores in the + * score set. + */ + HashSet scores = new HashSet(); + Iterator itMoves = moves.iterator(); + while (itMoves.hasNext()) { + double totalContrib = 0; + Move move = (Move) itMoves.next(); + Iterator objIt = objMap.keySet().iterator(); + while (objIt.hasNext()) { + Element elem = (Element) objIt.next(); + Set elemObj = (Set) objMap.get(elem); + Iterator elemObjIt = elemObj.iterator(); + while (elemObjIt.hasNext()) { + Objective obj = + (Objective)elemObjIt.next(); + if (obj instanceof + LocalityObjective) + ((LocalityObjective)obj) + .prepare(ldom, + (Resource)elem); + /* + * If the monitor is + * invalid, do not + * process + * WorkloadDependentObjectives + * since they have an + * implicit dependency + * on the monitor + * data. + */ + if (obj instanceof + WorkloadDependentObjective) + if (!isValid()) + continue; + double contrib = obj.calculate( + rwConf, move, elem); + if (contrib < -1 || contrib > 1) + throw new + IllegalOFValueException( + "x: " + contrib + + " is invalid, legal " + + "range is -1 <= x <= " + + "1"); + /* + * Modify the basic + * score by the + * importance of the + * objective and (if + * appropriate) the + * importance of an + * associated pool. + */ + if (resImp.containsKey(elem)) { + contrib *= ((Long) + resImp.get(elem)). + longValue(); + } + + totalContrib += contrib * + obj.getExpression(). + getImportance(); + } + } + Poold.OPT_LOG.log(Severity.DEBUG, + "scored move (" + move + ") " + + totalContrib); + scores.add(new ScoreMove(move, totalContrib)); + } + if (scores.size() != 0) { + /* + * Try to find a move to apply which + * yields a positive contribution. + */ + Object scoresArray[] = scores.toArray(); + Arrays.sort(scoresArray, + Collections.reverseOrder()); + if ((madeMove = processMoves(rwConf, + scoresArray, false)) == false) + madeMove = processMoves(rwConf, + scoresArray, true); + } else + Poold.OPT_LOG.log(Severity.INFO, + "no moves found"); + rwConf.close(); + Poold.OPT_LOG.log(Severity.DEBUG, + "synchronizing decision history"); + dh.syncToFile(dhPath); + } catch (Exception ex) { + rwConf.close(); + throw ex; + } + return (madeMove); + } + + /* + * Process the supplied array of scored moves, trying to find + * a move to apply. Return true if a move could be applied, + * false otherwise. + * + * @param conf The configuration to be modified. + * @param scores The areay of scored moves to be tried. + * @param ignoreDH Ignore Decision History details. + */ + private boolean processMoves(Configuration rwConf, Object scores[], + boolean ignoreDH) throws PoolsException, StaleMonitorException + { + boolean madeMove = false; + + for (int i = 0; i < scores.length; i++) { + ScoreMove move = (ScoreMove) scores[i]; + if (move.getScore() <= 0) { + if (ignoreDH) + Poold.OPT_LOG.log(Severity.INFO, + move + " not applied as " + + "benefit not significant"); + break; + } + if ((madeMove = applyMove(rwConf, move, ignoreDH)) == + true) + break; + } + return (madeMove); + } + + /* + * Attempt to apply the supplied move to the + * configuration. Return true if the move could be applied, + * false otherwise. + * + * @param conf The configuration to be modified. + * @param move The move to be applied. + * @param ignoreDH Ignore Decision History details. + */ + private boolean applyMove(Configuration conf, ScoreMove move, + boolean ignoreDH) + throws PoolsException, StaleMonitorException + { + boolean madeMove = false; + boolean wdpInvolved = false; + double utilization = 0.0; + + Poold.OPT_LOG.log(Severity.DEBUG, "selected " + move); + if (hasWorkloadDependentObjectives(move.getMove().getTo()) || + hasWorkloadDependentObjectives(conf)) { + Poold.OPT_LOG.log(Severity.DEBUG, + "Attempting to retrieve utilization for:" + move + .getMove().getTo()); + utilization = monitor.getUtilization(move + .getMove().getTo()); + wdpInvolved = true; + } + + /* + * Unless a move can be vetoed (i.e. decision history + * is effective and there are is a workload-dependent + * involved), the move should alwways be applied. + */ + if (ignoreDH || !wdpInvolved || !dh.veto(move.getMove(), + utilization)) { + Poold.OPT_LOG.log(Severity.INFO, + "applying move " + move.getMove()); + move.getMove().apply(); + ResourceMonitor mon = getMonitor().get(move.getMove(). + getFrom()); + mon.resetData("utilization"); + mon = getMonitor().get(move.getMove().getTo()); + mon.resetData("utilization"); + try { + Poold.OPT_LOG.log(Severity.DEBUG, + "committing configuration"); + conf.commit(0); + try { + if (move.getMove() instanceof + ComponentMove) + if (wdpInvolved) + dh.recordProcessorMove( + (ComponentMove)move + .getMove(), + utilization, + monitor + .getSampleCount()); + else + Poold.OPT_LOG.log( + Severity.DEBUG, + "decision not " + + "recorded due to " + + "lack of workload-" + + "dependent " + + "objectives"); + } catch (Exception e) { + Poold.OPT_LOG.log(Severity.INFO, + "couldn't update " + + "decision history (" + + e.toString() + ")"); + } + madeMove = true; + } catch (PoolsException pe) { + conf.rollback(); + Poold.OPT_LOG.log(Severity.INFO, + "move failed, possibly due to a " + + "bound process in a 1-processor " + + "set"); + } + } else { + /* + * Move was vetoed. + */ + if (!ignoreDH && wdpInvolved) + Poold.OPT_LOG.log(Severity.INFO, + move.getMove() + " not applied due to " + + "poor past results"); + } + return (madeMove); + } + + /** + * Add an objective based on the supplied expression to the + * supplied set of objectives. + * + * @param oSet Set of objectives to be extended + * @param type Type of element to which the expression is applied + * @param exp Expression to be used in the objective + * @throws IllegalArgumentException If a duplicate objective + * is identified or an invalid expression is supplied for this + * type of element + */ + private void addObjective(Set oSet, String type, Expression exp) + throws IllegalArgumentException + { + Objective o = AbstractObjective.getInstance(type, exp); + Poold.CONF_LOG.log(Severity.DEBUG, "parsed objective " + o); + /* + * Check the set of objectives and find contradictions. + */ + Iterator itObjs = oSet.iterator(); + while (itObjs.hasNext()) { + Objective other = (Objective) itObjs.next(); + if (o.getExpression().contradicts( + other.getExpression())) + throw new IllegalArgumentException( + "contradictory objectives:" + other + + ", " + o); + } + + if (oSet.add(o) != true) + throw new IllegalArgumentException( + "duplicate objective:" + o); + } + + /** + * Return a list of resource sets prepared to receive + * resources + * + * The list consists of all resource setss (of the supplied + * type) whose size is < their max constraint. + * + * @param resList The list of all resource sets from which + * recipients will be chosen + * @throws PoolsException if there is an error manipulation + * the pool resources + */ + private List getRecipients(List resList) throws PoolsException + { + List recipientList = new ArrayList(); + long size, max; + for (int i = 0; i < resList.size(); i++) { + Resource res; + res = (Resource)resList.get(i); + String type = res.getStringProperty("type"); + size = res.getLongProperty(type+".size"); + max = res.getLongProperty(type+".max"); + if (size < max) + recipientList.add(res); + } + return (recipientList); + } + + /** + * Return a list of resource sets prepared to donate resources + * + * The list consists of all resource sets (of the supplied + * type) whose size (minus the number of pinned resources + * where applicable) is > their min constraint. + * + * @param resList The list of all resource sets from which + * recipients will be chosen + * @throws PoolsException if there is an error manipulation + * the pool resources + */ + private List getDonors(List resList) throws PoolsException + { + List donorList = new ArrayList(); + long size, min; + for (int i = 0; i < resList.size(); i++) { + Value bValue; + Resource res; + List pinned; + ArrayList valueList = new ArrayList(); + + res = (Resource)resList.get(i); + String type = res.getStringProperty("type"); + size = res.getLongProperty(type+".size"); + bValue = new Value("cpu.pinned", true); + valueList.add(bValue); + pinned = res.getComponents(valueList); + bValue.close(); + min = res.getLongProperty(type+".min"); + if (pinned.size() > min) + size -= pinned.size() - min; + if (size > min) + donorList.add(res); + } + return (donorList); + } + + /** + * Return a list of Processors for the supplied resource. + * + * The list consists of all Processors (excluding the pinned + * Processors) in the set. + * + * @param set The resource for which Processors should be found + * @throws PoolsException if there is an error manipulation + * the pool resources + */ + private List getProcessors(Resource set) throws PoolsException + { + Iterator it = set.getComponents(null).iterator(); + List ret = new ArrayList(); + + while (it.hasNext()) { + Component cpu = (Component) it.next(); + try + { + if (cpu.getBoolProperty("cpu.pinned") == false) + ret.add(cpu); + } catch (PoolsException pe) + { + ret.add(cpu); + } + } + return (ret); + } + + /** + * Return true if the solver is capable of working with + * statistically valid data. + */ + public boolean isValid() + { + return (monitor.isValid()); + } + + /** + * Return the monitor used by this solver. + */ + public Monitor getMonitor() + { + return (monitor); + } + + /** + * Return the set of objectives associated with the supplied + * element. + * + * @param elem Retrieve objectives for this element. + */ + public Set getObjectives(Element elem) + { + return ((Set)objMap.get(elem)); + } + + /** + * Holds details about the score of a proposed configuration + * move. Each move must be scored so that they can ranked in + * terms of increasing desirability + */ + static class ScoreMove implements Comparable { + /** + * The move which is being scored. + */ + private final Move m; + + /** + * The score of the move. + */ + private final double score; + + /** + * Score formatter. + */ + private static final DecimalFormat scoreFormat = + new DecimalFormat("0.00"); + + /** + * Constructor. + * + * @param m The move under consideration. + * @param score The score of the move. + */ + public ScoreMove(Move m, double score) + { + this.m = m; + this.score = score; + } + + public int compareTo(Object o) + { + ScoreMove other = (ScoreMove) o; + + return ((score < other.getScore()) ? -1 : + (score > other.getScore()) ? 1 : 0); + } + + public String toString() + { + return ("move (" + m + ") score " + + scoreFormat.format(score)); + } + + /** + * Return the score. + */ + double getScore() + { + return (score); + } + + /** + * Return the move. + */ + Move getMove() + { + return (m); + } + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/package.html new file mode 100644 index 0000000000..6b34156ec0 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/domain/pools/package.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +Provides classes for automated resource management in Solaris. + + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2002/287/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, please see: +<ul> + <li><a href="http://taxman.eng/projects/dynamic-resource-pools/">Dynamic Resource Pools Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/Makefile new file mode 100644 index 0000000000..b20cd0bac2 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/Makefile @@ -0,0 +1,47 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/service/exception/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + +SOURCE = SuccinctStackTraceFormatter.java + +all install: $(SOURCE:.java=.class) + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/SuccinctStackTraceFormatter.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/SuccinctStackTraceFormatter.java new file mode 100644 index 0000000000..d02e0f6a25 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/SuccinctStackTraceFormatter.java @@ -0,0 +1,142 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* ident "%Z%%M% %I% %E% SMI" */ + +package com.sun.solaris.service.exception; + +import java.io.*; + +/** + * Formats a stack trace in a single line. The format is meant to + * convey the stack trace as a sequence of class names and line numbers, + * with the topmost frame first, suitable for logging. Beware, the + * format may evolve. + */ +public class SuccinctStackTraceFormatter { + /** + * Formats a Throwable and adds an optional description string. + * The string should be suitable to precede the top stack + * element, and include any punctuation that should + * differentiate it from the element. + */ + public static String formatWithDescription(Throwable t, + String description) + { + StringBuffer s = new StringBuffer(); + + s.append("("); + + if (description != null) + s.append(description); + + s.append(t.getClass().getName()); + s.append(", "); + StackTraceElement[] trace = t.getStackTrace(); + for (int i = 0; i < trace.length; i++) { + appendStackTraceElement(i > 0 ? trace[i - 1] : null, + trace[i], s); + if (i != trace.length - 1) + s.append(", "); + } + s.append(")"); + + if (t.getCause() != null) { + s.append(" caused by "); + s.append(format(t.getCause())); + } + + return (s.toString()); + } + + /** + * Formats a Throwable's stack trace. The format is meant to be + * a single line of output, conveying the stack trace as a + * sequence of class names and line numbers, with the topmost + * frame first, suitable for logging. If two adjacent stack + * trace elements share some portion of a class name, the + * bottommost element may have the common part replaced with an + * ampersand. + */ + public static String format(Throwable t) + { + return (formatWithDescription(t, null)); + } + + /** + * Formats a stack trace element as per <code>format()</code>. + */ + private static void appendStackTraceElement(StackTraceElement last, + StackTraceElement e, StringBuffer s) + { + /* + * This could grab more of a common class name. (See + * SuccinctStackTraceFormatter.format()) + */ + if (last == null || !last.getClassName().equals( + e.getClassName())) { + s.append(e.getClassName()); + s.append("."); + } else + s.append("&."); + + s.append(e.getMethodName()); + if (e.getLineNumber() > 0) { + s.append(":"); + s.append(e.getLineNumber()); + } + if (e.isNativeMethod()) { + s.append(":"); + s.append("native"); + } + } + + public static void printStackTrace(Throwable t) + { + printStackTrace(t, System.err); + } + + public static void printStackTrace(Throwable t, PrintStream out) + { + out.print(t); + out.print(" at "); + out.print(format(t)); + } + + public static final void main(String args[]) + { + SuccinctStackTraceFormatter.printStackTrace(big()); + } + + public static final Throwable big() { + return new Throwable().initCause(little()); + } + + public static final Throwable little() { + return new Throwable(); + } + +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/package.html new file mode 100644 index 0000000000..38ff408766 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/exception/package.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +Provides service-related exceptions and classes for generating or +interpreting them. + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2002/287/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, +please see: +<ul> + <li><a href="http://taxman.eng/projects/dynamic-resource-pools/">Dynamic Resource Pools Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/Kstat.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/Kstat.java new file mode 100644 index 0000000000..54b1f91be2 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/Kstat.java @@ -0,0 +1,80 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.kstat; + +import com.sun.solaris.service.pools.*; + +/** + * Wraps <code>libkstat(3lib)</code>. See + * <code>/usr/include/sys/kstat.h</code> for details. + */ +public final class Kstat { + /** + * Pointer to native <code>kstat_ctl_t</code>. + */ + private long kctl; + + /** + * Pointer to native <code>kstat_t</code>. + */ + private long ksp; + + Kstat(long kctl, long ksp) + { + this.kctl = kctl; + this.ksp = ksp; + } + + /** + * Returns the kstat's <code>ks_snaptime</code> field. + */ + public native HRTime getSnapTime(); + + /** + * Returns the kstat's <code>ks_crtime</code> field. + */ + public native HRTime getCreationTime(); + + /** + * Returns the named value -- the value of the named kstat, or + * field in a raw kstat, as applicable, and available. Returns + * <i>null</i> if no such named kstat or field is available. + * + * @throws KstatTypeNotSupportedException if the raw kstat is not + * understood. (Presenstly, none are.) + */ + public native Object getValue(String name) + throws KstatTypeNotSupportedException; + + /** + * Invokes <code>kstat_read(3kstat)</code> for tho underlying kstat. + * Throws KstatException if the native function returns an error. + */ + public native void read() throws KstatReadException; +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatChainUpdateException.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatChainUpdateException.java new file mode 100644 index 0000000000..82a9612dfc --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatChainUpdateException.java @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.kstat; + +/** + * Indicates a that <code>kstat_chain_update(3KSTAT)</code> failed for the + * given KstatCtl. + */ +public class KstatChainUpdateException extends KstatException { + /** + * The offending KstatCtl. + */ + private KstatCtl kstatCtl; + + public KstatChainUpdateException(KstatCtl kctl) + { + this.kstatCtl = kstatCtl; + } + + /** + * Returns the offending KstatCtl. + */ + public KstatCtl getKstatCtl() + { + return (kstatCtl); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatCtl.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatCtl.java new file mode 100644 index 0000000000..a18727db55 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatCtl.java @@ -0,0 +1,94 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.kstat; + +/** + * <code>kstat</code> controlling object. Allows kstats to be looked up + * so they can later be sampled. + */ +public final class KstatCtl +{ + static { + System.loadLibrary("jkstat"); + KstatCtl.init(); + } + + /** + * Pointer to a <code>kstat_ctl_t</code>. + */ + private long kctl; + + /** + * Invokes <code>kstat_open(3KSTAT)</code>. The returned object + * should be explicitly finalized when it's no longer needed. + */ + public KstatCtl() + { + kctl = open(); + assert(kctl != 0); + } + + /** + * Calls <code>kstat_close(3KSTAT)</code>. + */ + public void finalize() + { + close(kctl); + kctl = 0; + } + + /** + * Invokes <code>kstat_open(3KSTAT)</code>. + */ + private native long open(); + + /** + * Invokes <code>kstat_close(3KSTAT)</code>. + */ + private native int close(long kctl); + + /** + * Invokes <code>kstat_lookup(3KSTAT)</code> and returns a Kstat + * for any result, or null if none is found. + */ + public native Kstat lookup(String module, int instance, String name); + + /** + * Invokes <code>kstat_chain_update(3KSTAT)</code>. + * + * @throws KstatChainUpdateException if the native function + * returns -1. + */ + public native void chainUpdate() throws KstatChainUpdateException; + + /** + * Initialize cached class, method, and field IDs. + */ + private static native void init(); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatException.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatException.java new file mode 100644 index 0000000000..34867cd11e --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatException.java @@ -0,0 +1,36 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.kstat; + +/** + * Abstract base class from which kstat-related exceptions are + * descended. + */ +public abstract class KstatException extends Exception { +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatReadException.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatReadException.java new file mode 100644 index 0000000000..f3e682f77c --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatReadException.java @@ -0,0 +1,35 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.kstat; + +/** + * Indicates a that <code>kstat_read</code> failed for the given Kstat. + */ +public class KstatReadException extends KstatException { +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatTypeNotSupportedException.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatTypeNotSupportedException.java new file mode 100644 index 0000000000..648ac236a0 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/KstatTypeNotSupportedException.java @@ -0,0 +1,36 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.kstat; + +/** + * Indicates a that <code>Kstat.getValue()</code> was invoked for a raw + * kstat whose structure is not understood. + */ +public class KstatTypeNotSupportedException extends KstatException { +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/Makefile new file mode 100644 index 0000000000..cc3b61b363 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/Makefile @@ -0,0 +1,52 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/service/kstat/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + +SOURCE = Kstat.java \ + KstatChainUpdateException.java \ + KstatCtl.java \ + KstatException.java \ + KstatReadException.java \ + KstatTypeNotSupportedException.java + +all install: $(SOURCE:.java=.class) + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/package.html new file mode 100644 index 0000000000..3eee0d0b3e --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/kstat/package.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +kstat(9S) interfaces. + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2002/287/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, +please see: +<ul> + <li><a href="http://taxman.eng/projects/dynamic-resource-pools/">Dynamic Resource Pools Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/LocalityDomain.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/LocalityDomain.java new file mode 100644 index 0000000000..a0b4c7aa3a --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/LocalityDomain.java @@ -0,0 +1,350 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.locality; + +import java.util.*; + +import com.sun.solaris.service.pools.*; + +/** + * A representation of the Locality Groups for a single Solaris + * instance. + */ +public class LocalityDomain +{ + /** + * Obtain a Locality Group snapshot based on the view + * available to the caller. + */ + public static final int LGRP_VIEW_CALLER = 0; + + /** + * Obtain a Locality Group snapshot based on the view + * of the Operating System. + */ + public static final int LGRP_VIEW_OS = 1; + + static + { + System.loadLibrary("jlgrp"); + } + + /** + * The view used to create this LocalityDomain. + */ + private int view; + + /** + * The cookie which represents the snapshot of locality + * information held by the lgrp library. + */ + private long cookie; + + /** + * The root LocalityGroup for the LocalityDomain + */ + private LocalityGroup root; + + /** + * Cached value of maxLatency. + */ + private final int maxLatency; + + /** + * String representation of often used property. + */ + private final static String CPU_SYS_ID = "cpu.sys_id"; + + /** + * Constructor. + * + * @param view to use when creating the LocalityDomain. + * @throws Exception if there is a problem initializing the + * lgrp snapshot. + */ + public LocalityDomain(int view) throws Exception + { + this.view = view; + cookie = jl_init(view); + root = jl_root(); + /* + * The maxLatency calculation is expensive and is used + * every time a locality objective is examined. Since + * it will never change over the lifetime of a + * LocalityDomain, we calculate it once in the + * constructor and cache for future use. + */ + maxLatency = calcMaxLatency(); + } + + /** + * Reclaim the resource allocated by the C proxy. + * + * @throws Throwable if there is a problem reclaiming the reosurces. + */ + protected void finalize() throws Throwable + { + try + { + close(); + } + finally + { + super.finalize(); + } + } + + /** + * Return the "root" LocalityGroup. + */ + public LocalityGroup getRoot() + { + return (root); + } + + /** + * Close this LocalityDomain. Resources are reclaimed in the C + * proxy and this LocalityDomain should never be used + * again. None of the LocalityGroups which are referenced from + * this LocalityDomain should be used after this method is + * invoked. NB: jl_fini returns a success indicator which is + * ignored as we are closing this domain. + */ + public void close() + { + if (cookie != 0) { + jl_fini(); + cookie = 0; + root = null; + } + } + + /** + * Return a string representation of this instance. + */ + public String toString() + { + return (root.toString()); + } + + /** + * Return the groups in this domain to which the supplied cpus + * belong, excluding the supplied set of groups. + * + * @param exclude Set of groups to be excluded. + * @param cpus List of cpus + * + * @throws PoolsException if there is an error accessing the + * cpu details. + */ + public Set foreignGroups(Set exclude, List cpus) throws PoolsException + { + Iterator cpuIt = cpus.iterator(); + Set result = new HashSet(); + while (cpuIt.hasNext()) { + Component comp = (Component) cpuIt.next(); + int id = (int) comp.getLongProperty(CPU_SYS_ID); + LocalityGroup group = getGroup(id); + if (group != null && exclude.contains(group) == false) + result.add(group); + } + return (result); + } + + /** + * Return the locality group which contains the majority of + * the cpus in the supplied list. If more than one group + * satisfies this criteria, then the choice of group is + * deterministic but unspecified. + * + * @param cpus List of cpus to be examined. + * + * @throws PoolsException if there is an error accessing the + * cpu details. + */ + public LocalityGroup getRepresentativeGroup(List cpus) + throws PoolsException + { + Iterator cpuIt = cpus.iterator(); + Map grps = new HashMap(); + while (cpuIt.hasNext()) { + Component comp = (Component) cpuIt.next(); + int id = (int) comp.getLongProperty(CPU_SYS_ID); + LocalityGroup group = getGroup(id); + Integer score = (Integer) grps.get(group); + if (score != null) { + int iscore = score.intValue() + 1; + grps.put(group, new Integer(iscore)); + } else { + grps.put(group, new Integer(1)); + } + } + Iterator groupIt = grps.keySet().iterator(); + LocalityGroup centre = null; + Integer highest = new Integer(0); + while (groupIt.hasNext()) { + LocalityGroup cand = (LocalityGroup) groupIt.next(); + Integer value = (Integer) grps.get(cand); + if (value.intValue() > highest.intValue()) { + highest = value; + centre = cand; + } + } + return (centre); + } + + /** + * Return the maximum latency between the groups in this + * domain. + * + */ + private int calcMaxLatency() + { + int max = 0; + + Set groups = getGroups(); + Iterator outer = groups.iterator(); + while (outer.hasNext()) { + Iterator inner = groups.iterator(); + LocalityGroup g1 = (LocalityGroup) outer.next(); + while (inner.hasNext()) { + LocalityGroup g2 = (LocalityGroup) inner.next(); + int latency = g1.getLatency(g2); + if (latency > max) + max = latency; + } + } + return (max); + } + + /** + * Return the maximum possible latency between all locality + * groups in this domain. + */ + public int getMaxLatency() + { + return (maxLatency); + } + + /** + * Return the set of all LocalityGroups for this LocalityDomain. + */ + public Set getGroups() + { + Set groups = new HashSet(); + groups.add(root); + getGroups(root, groups); + return (groups); + } + + /** + * Add all the descendent LocalityGroups for the supplied + * group into the supplied set. + * + * @param group is the group whose descendents are processed. + * @param descendents the set to add descendents of group. + */ + private void getGroups(LocalityGroup group, Set descendents) + { + Set children = group.getChildren(); + + if (! children.isEmpty()) { + Iterator itChild = children.iterator(); + while (itChild.hasNext()) { + LocalityGroup child = (LocalityGroup) itChild. + next(); + getGroups(child, descendents); + } + descendents.addAll(children); + } + } + + /** + * Return the LocalityGroup containing the supplied CPU + * id. Search all LocalityGroups starting at the root group. + * + * @param cpuid is the sys-id of the CPU to search for. + */ + public LocalityGroup getGroup(int cpuid) + { + LocalityGroup answer = getGroup(root, cpuid); + return (getGroup(root, cpuid)); + } + + /** + * Return the LocalityGroup containing the supplied CPU + * id. Search LocalityGroups starting at the supplied group. + * + * @param group is the group to start searching from. + * @param cpuid is the sys-id of the CPU to search for. + */ + private LocalityGroup getGroup(LocalityGroup group, int cpuid) + { + Set children = group.getChildren(); + + if (children.isEmpty()) { + int cpus[] = group.getCPUIDs(); + + + for (int i = 0; i < cpus.length; i++) + if (cpus[i] == cpuid) { + return (group); + } + } else { + Iterator itGroup = children.iterator(); + while (itGroup.hasNext()) { + LocalityGroup owner; + LocalityGroup child = (LocalityGroup) itGroup. + next(); + if ((owner = getGroup(child, cpuid)) != null) + return (owner); + } + } + return (null); + } + + /** + * Initialise the LocalityDomain with an lgrp snapshot. + * + * @param view is the type of snapshot to obtain. + */ + private native long jl_init(int view) throws Exception; + + /** + * Release the lgrp snapshot. + */ + private native int jl_fini(); + + /** + * Find the root LocalityGroup. + */ + private native LocalityGroup jl_root(); + +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/LocalityGroup.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/LocalityGroup.java new file mode 100644 index 0000000000..f0d8694bdf --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/LocalityGroup.java @@ -0,0 +1,211 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.locality; + +import java.util.*; + +import com.sun.solaris.service.pools.*; + +/** + * A representation of an individual Locality Group. A Locality Group + * resides within a Locality Domain. + */ +public class LocalityGroup +{ + /** + * The locality domain which contains this group. + */ + private LocalityDomain domain; + + /** + * The C proxy id for this instance. + */ + private long id; + + /** + * The parent group of this instance. + */ + private LocalityGroup parent; + + /** + * The array of CPU IDs which are assigned to this instance. + */ + private int cpu_ids[]; + + /** + * The child groups of this instance. + */ + private Set children; + + /** + * Constructor. + * + * @param domain is the domain to which this instance belongs. + * @param id is the id of this instance. + * @param parent is the parent of this instance. + */ + public LocalityGroup(LocalityDomain domain, long id, + LocalityGroup parent) + { + this.domain = domain; + this.id = id; + this.parent = parent; + this.cpu_ids = jl_cpus(); + long nativeChildren[] = jl_children(); + children = new HashSet(); + for (int i = 0; i < nativeChildren.length; i++) + children.add(new LocalityGroup(domain, + nativeChildren[i], this)); + } + + /** + * Return a string representation of this instance. + */ + public String toString() + { + StringBuffer sb = new StringBuffer().append("locality group ") + .append(id) + .append(" with cpus ["); + + String sep = ""; + for (int i = 0; i < cpu_ids.length; i++) { + sb.append(sep); + sb.append(cpu_ids[i]); + sep = " "; + } + sb.append("]"); + + return (sb.toString()); + } + + /** + * Return the set of child locality groups for this instance. + */ + public Set getChildren() + { + return (children); + } + + /** + * Return the array of CPU IDs which belong to this locality + * group. + */ + public int[] getCPUIDs() + { + return (cpu_ids); + } + + /** + * Return the locality group ID. + */ + long getID() + { + return (id); + } + + /** + * Return the latency of the supplied group with respect to + * this group. + * + * @param other is another locality group belonging to the + * same LocalityDomain. + */ + public int getLatency(LocalityGroup other) + { + return (jl_latency(id, other.getID())); + } + + /** + * Return the number of Latency Groups to which these cpus + * belong which are not part of this group. + * + * @param cpus List of cpus to be examined. + * + * @throws PoolsException if there is an error accessing the + * cpu details. + */ + public int countForeignGroups(List cpus) throws PoolsException + { + Set groups = new HashSet(); + Iterator cpuIt = cpus.iterator(); + + while (cpuIt.hasNext()) { + Component comp = (Component) cpuIt.next(); + int id = (int) comp.getLongProperty("cpu.sys_id"); + for (int i = 0; i < cpu_ids.length; i++) { + if (cpu_ids[i] == id) { + LocalityGroup other = domain. + getGroup(id); + if (other != this && + groups.contains(other) == false) + groups.add(other); + } + } + } + return (groups.size()); + } + + public Set contains(List cpus) throws PoolsException + { + Set contained = new HashSet(); + Iterator cpuIt = cpus.iterator(); + int set_cpus[] = getCPUIDs(); + + while (cpuIt.hasNext()) { + Component comp = (Component) cpuIt.next(); + for (int i = 0; i < set_cpus.length; i++) { + if (set_cpus[i] == (int)comp.getLongProperty( + "cpu.sys_id")) { + contained.add(comp); + break; + } + } + } + return (contained); + } + + /** + * Return an array containing the child locality group IDs. + */ + private native long[] jl_children(); + + /** + * Return an array of CPU IDs within this locality group. + */ + private native int[] jl_cpus(); + + /** + * Return the latency between the two supplied lgrp IDs. + * + * @param id1 is the first id. + * @param id2 is the second id. + */ + private native int jl_latency(long id1, long id2); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/Makefile new file mode 100644 index 0000000000..65adde7df1 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/Makefile @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/service/locality/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + +SOURCE = LocalityDomain.java \ + LocalityGroup.java + +all install: $(SOURCE:.java=.class) + + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/package.html new file mode 100644 index 0000000000..74fa4be14c --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/locality/package.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +Provides classes for manipulating Solaris Locality Groups. + + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2003/034/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, please see: +<ul> + <li><a href="http://lgrp.eng/">Memory Hierarchy Aware Solaris Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Facility.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Facility.java new file mode 100644 index 0000000000..0056164d17 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Facility.java @@ -0,0 +1,261 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* ident "%Z%%M% %I% %E% SMI" */ + +package com.sun.solaris.service.logging; + +/** + * <code>syslog(3C)</code> facility levels defined in + * <code>sys/syslog.h</code>. + */ +public class Facility { + /** + * LOG_KERN from <code>sys/syslog.h</code> + */ + private static final int LOG_KERN = 0 << 3; + + /** + * LOG_USER from <code>sys/syslog.h</code> + */ + private static final int LOG_USER = 1 << 3; + + /** + * LOG_MAIL from <code>sys/syslog.h</code> + */ + private static final int LOG_MAIL = 2 << 3; + + /** + * LOG_DAEMON from <code>sys/syslog.h</code> + */ + private static final int LOG_DAEMON = 3 << 3; + + /** + * LOG_AUTH from <code>sys/syslog.h</code> + */ + private static final int LOG_AUTH = 4 << 3; + + /** + * LOG_SYSLOG from <code>sys/syslog.h</code> + */ + private static final int LOG_SYSLOG = 5 << 3; + + /** + * LOG_LPR from <code>sys/syslog.h</code> + */ + private static final int LOG_LPR = 6 << 3; + + /** + * LOG_NEWS from <code>sys/syslog.h</code> + */ + private static final int LOG_NEWS = 7 << 3; + + /** + * LOG_UUCP from <code>sys/syslog.h</code> + */ + private static final int LOG_UUCP = 8 << 3; + + /** + * LOG_CRON from <code>sys/syslog.h</code> + */ + private static final int LOG_CRON = 15 << 3; + + /** + * LOG_LOCAL0 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL0 = 16 << 3; + + /** + * LOG_LOCAL1 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL1 = 17 << 3; + + /** + * LOG_LOCAL2 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL2 = 18 << 3; + + /** + * LOG_LOCAL3 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL3 = 19 << 3; + + /** + * LOG_LOCAL4 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL4 = 20 << 3; + + /** + * LOG_LOCAL5 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL5 = 21 << 3; + + /** + * LOG_LOCAL6 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL6 = 22 << 3; + + /** + * LOG_LOCAL7 from <code>sys/syslog.h</code> + */ + private static final int LOG_LOCAL7 = 23 << 3; + + /** + * LOG_KERN <code>syslog(3C)</code> facility + */ + public static final Facility KERN = new Facility(LOG_KERN, "KERN"); + + /** + * LOG_USER <code>syslog(3C)</code> facility + */ + public static final Facility USER = new Facility(LOG_USER, "USER"); + + /** + * LOG_MAIL <code>syslog(3C)</code> facility + */ + public static final Facility MAIL = new Facility(LOG_MAIL, "MAIL"); + + /** + * LOG_DAEMON <code>syslog(3C)</code> facility + */ + public static final Facility DAEMON = new Facility(LOG_DAEMON, + "DAEMON"); + + /** + * LOG_AUTH <code>syslog(3C)</code> facility + */ + public static final Facility AUTH = new Facility(LOG_AUTH, "AUTH"); + + /** + * LOG_SYSLOG <code>syslog(3C)</code> facility + */ + public static final Facility SYSLOG = new Facility(LOG_SYSLOG, + "SYSLOG"); + + /** + * LOG_LPR <code>syslog(3C)</code> facility + */ + public static final Facility LPR = new Facility(LOG_LPR, "LPR"); + + /** + * LOG_NEWS <code>syslog(3C)</code> facility + */ + public static final Facility NEWS = new Facility(LOG_NEWS, "NEWS"); + + /** + * LOG_UUCP <code>syslog(3C)</code> facility + */ + public static final Facility UUCP = new Facility(LOG_UUCP, "UUCP"); + + /** + * LOG_CRON <code>syslog(3C)</code> facility + */ + public static final Facility CRON = new Facility(LOG_CRON, "CRON"); + + /** + * LOG_LOCAL0 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL0 = new Facility(LOG_LOCAL0, + "LOCAL0"); + + /** + * LOG_LOCAL1 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL1 = new Facility(LOG_LOCAL1, + "LOCAL1"); + + /** + * LOG_LOCAL2 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL2 = new Facility(LOG_LOCAL2, + "LOCAL2"); + + /** + * LOG_LOCAL3 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL3 = new Facility(LOG_LOCAL3, + "LOCAL3"); + + /** + * LOG_LOCAL4 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL4 = new Facility(LOG_LOCAL4, + "LOCAL4"); + + /** + * LOG_LOCAL5 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL5 = new Facility(LOG_LOCAL5, + "LOCAL5"); + + /** + * LOG_LOCAL6 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL6 = new Facility(LOG_LOCAL6, + "LOCAL6"); + + /** + * LOG_LOCAL7 <code>syslog(3C)</code> facility + */ + public static final Facility LOCAL7 = new Facility(LOG_LOCAL7, + "LOCAL7"); + + /** + * Native facility of this instance. + */ + private int facility; + + /** + * Name of this facility. + */ + private String string; + + private Facility(int facility, String string) + { + this.facility = facility; + this.string = string; + } + + /** + * Returns the native <code>syslog(3C)</code> facility. + */ + public int getNative() + { + return (facility); + } + + public boolean equals(Object o) + { + Facility f = (Facility)o; + + return (getNative() == f.getNative()); + } + + public String toString() + { + return (string); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Makefile new file mode 100644 index 0000000000..1d4f8519b5 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Makefile @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/service/logging/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + +SOURCE = Facility.java \ + Severity.java \ + SyslogHandler.java \ + SysloglikeFormatter.java + +all install: $(SOURCE:.java=.class) + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Severity.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Severity.java new file mode 100644 index 0000000000..ecd5d8d14c --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/Severity.java @@ -0,0 +1,254 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* ident "%Z%%M% %I% %E% SMI" */ + +package com.sun.solaris.service.logging; + +import java.util.*; +import java.util.logging.*; + +/** + * <code>syslog(3C)</code> severity levels defined in + * <code>sys/syslog.h</code>. + */ +public final class Severity extends Level { + /** + * LOG_EMERG from <code>sys/syslog.h</code> + */ + private static final int LOG_EMERG = 0; + + /** + * LOG_ALERT from <code>sys/syslog.h</code> + */ + private static final int LOG_ALERT = 1; + + /** + * LOG_CRIT from <code>sys/syslog.h</code> + */ + private static final int LOG_CRIT = 2; + + /** + * LOG_ERR from <code>sys/syslog.h</code> + */ + private static final int LOG_ERR = 3; + + /** + * LOG_WARNING from <code>sys/syslog.h</code> + */ + private static final int LOG_WARNING = 4; + + /** + * LOG_NOTICE from <code>sys/syslog.h</code> + */ + private static final int LOG_NOTICE = 5; + + /** + * LOG_INFO from <code>sys/syslog.h</code> + */ + private static final int LOG_INFO = 6; + + /** + * LOG_DEBUG from <code>sys/syslog.h</code> + */ + private static final int LOG_DEBUG = 7; + + /** + * Maps static instances by name. + */ + private static final HashMap severityMap = new HashMap(); + + /** + * LOG_EMERG + */ + public static final Severity EMERG = new Severity(LOG_EMERG, + Level.SEVERE.intValue() - 1, "EMERG"); + + /** + * LOG_ALERT + */ + public static final Severity ALERT = new Severity(LOG_ALERT, + Level.SEVERE.intValue() - 2, "ALERT"); + + /** + * LOG_CRIT + */ + public static final Severity CRIT = new Severity(LOG_CRIT, + Level.SEVERE.intValue() - 3, "CRIT"); + + /** + * LOG_ERR + */ + public static final Severity ERR = new Severity(LOG_ERR, + Level.SEVERE.intValue() - 4, "ERR"); + + /** + * LOG_WARNING + */ + public static final Severity WARNING = new Severity(LOG_WARNING, + Level.WARNING.intValue() - 1, "WARNING"); + + /** + * LOG_NOTICE + */ + public static final Severity NOTICE = new Severity(LOG_NOTICE, + Level.INFO.intValue() - 1, "NOTICE"); + + /** + * LOG_INFO + */ + public static final Severity INFO = new Severity(LOG_INFO, + Level.INFO.intValue() - 2, "INFO"); + + /** + * LOG_DEBUG + */ + public static final Severity DEBUG = new Severity(LOG_DEBUG, + Level.FINE.intValue() - 1, "DEBUG"); + + /** + * Add aliases. + */ + static { + severityMap.put("WARN", Severity.WARNING); + severityMap.put("ERROR", Severity.ERR); + } + + /** + * Disallowed overidden constant Level + */ + private static final Level SEVERE = null; + + /** + * Disallowed overidden constant Level + */ + private static final Level CONFIG = null; + + /** + * Disallowed overidden constant Level + */ + private static final Level FINE = null; + + /** + * Disallowed overidden constant Level + */ + private static final Level FINER = null; + + /** + * Disallowed overidden constant Level + */ + private static final Level FINEST = null; + + /** + * See getNative(). + */ + private int severity; + + /** + * Constructs a Severity with the given native severity, Java + * logging level, and name. + */ + private Severity(int severity, int level, String name) + { + super(name, level); + this.severity = severity; + + Object displaced = severityMap.put(name, this); + assert (displaced == null); + } + + /** + * Returns the Severity closest in meaning to the given Level. + * This is meant to be used by SyslogHandler to determine a + * proper Severity for Records which only specify a Level. + * + * <ul> + * <li>Level.SEVERE or higher becomes Severity.ERR + * <li>Level.WARNING becomes Severity.WARNING + * <li>Level.INFO becomes Severity.INFO + * <li>Level.FINE becomes Severity.DEBUG + * </ul> + * + * If the level is below Level.FINE, i.e. the level is too low + * for syslog, then null is returned. + */ + public static Severity severityForLevel(Level l) + { + if (l instanceof Severity) + return (Severity)l; + else { + if (l.intValue() >= Level.SEVERE.intValue()) + return (ERR); + if (l.intValue() >= Level.WARNING.intValue()) + return (WARNING); + if (l.intValue() >= Level.INFO.intValue()) + return (INFO); + if (l.intValue() >= Level.CONFIG.intValue()) + return (INFO); + if (l.intValue() >= Level.FINE.intValue()) + return (DEBUG); + return (null); + } + } + + /** + * Returns the native <code>syslog(3C)</code> severity. + */ + public int getNative() + { + return (severity); + } + + /** + * Returns the Severity object with the given name, interpreted + * case-insensitively. + * + * @throws IllegalArgumentException if the name isn't of a known + * severity. + */ + public static Level parse(String name) + { + Severity severity = (Severity)severityMap.get( + name.toUpperCase()); + + if (severity == null) + throw new IllegalArgumentException(); + else + return (severity); + } + + /** + * Returns the Severity object with the given name, interpreted + * case-insensitively. + * + * @throws IllegalArgumentException if the name isn't of a known + * severity. + */ + public static Severity getSeverityWithName(String name) + { + return ((Severity)parse(name)); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/SyslogHandler.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/SyslogHandler.java new file mode 100644 index 0000000000..9764b2b5bb --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/SyslogHandler.java @@ -0,0 +1,267 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* ident "%Z%%M% %I% %E% SMI" */ + +package com.sun.solaris.service.logging; + +import java.text.*; +import java.util.*; +import java.util.logging.Formatter; +import java.util.logging.Handler; +import java.util.logging.LogRecord; + +import com.sun.solaris.service.exception.SuccinctStackTraceFormatter; + +/** + * This handler outputs LogRecords with <code>syslog(3C)</code> to the + * given facility with a severity translated by Level with a fixed + * table. Formatters are not used. + * + * Multiple SyslogHandlers may not be in concurrent use in one virtual + * machine. + */ +public final class SyslogHandler extends Handler { + /** + * <code>syslog(3C)</code> ident string, prepended to every + * message. + */ + private String ident; + + /** + * <code>syslog</code> facility to be logged to. + */ + private Facility facility; + + /** + * Records the instance of this singleton. + */ + private static SyslogHandler instance = null; + + /** + * Flag whether stack traces should be output when a record's + * <code>thrown</code> field is set. They will be formatted in + * a single line by <code>SuccinctStackTraceFormatter</code>, + * which does not include the Throwable's description, since + * it's presumably described by the log message). Default + * <code>true</code>. + */ + private static boolean useStackTraces = true; + + /** + * Default logging option value. Sets no options. (Corresponds + * to the <code>logopt</code> argument to openlog(3c).) + */ + private static final int DEF_LOGOPT = 0; + + /** + * Flag to set whether log records should indicate the record's + * logger. (default false) + */ + private boolean useLoggerName = false; + + /** + * Flag to set whether log records should indicate the last + * component of the record's logger name, if useLoggerName isn't + * set. (default true) + */ + private boolean useShortLoggerName = true; + + static { + System.loadLibrary("jsyslog"); + } + + private SyslogHandler(String ident, Facility facility) + { + if (ident == null || facility == null) + throw new IllegalArgumentException(); + + this.ident = ident; + this.facility = facility; + + openlog(ident, DEF_LOGOPT, facility.getNative()); + instance = this; + } + + /** + * Return this virtual machine's instance of SyslogHandler, + * creating one which logs with the given identity to the given + * facility if necessary, unless an instance with a different + * identity or facility is already open, in which case an + * IllegalArgumentException is thrown. + * + * @throws IllegalArgumentException if the requested identity or + * facility differs from a previously-created instance. + */ + public static SyslogHandler getInstance(String ident, + Facility facility) + { + if (instance != null) { + if (!instance.ident.equals(ident) || + !instance.facility.equals(facility)) + throw new IllegalArgumentException(); + else + return (instance); + } else + return (instance = new SyslogHandler(ident, facility)); + } + + public void finalize() + { + try { + close(); + } catch (Exception e) { + // superclass-defined exceptions do not apply + } + } + + public String toString() + { + return ("SyslogHandler(" + ident + ", " + facility.toString() + + ")"); + } + + /** + * Calls <code>syslog(3C)</code>. + */ + private static native void syslog(int severity, String message); + + /** + * Calls <code>openlog(3C)</code>. + */ + private static native void openlog(String ident, int logopt, + int facility); + + /** + * Calls <code>closelog(3C)</code>. + */ + private static native void closelog(); + + /** + * Publishes the given record with its associated Severity (or + * infers its severity with Severity.severityForLevel(), if + * another type of Level is used), if the result is non-null. + */ + public void publish(LogRecord record) + { + Severity severity; + + if (record.getLevel() instanceof Severity) + severity = (Severity)record.getLevel(); + else + severity = Severity.severityForLevel(record + .getLevel()); + + if (getLevel().intValue() > severity.intValue()) + return; + + /* + * If the severity is null, the message isn't meant to + * be sent to syslog. + */ + if (severity == null) + return; + + StringBuffer message = new StringBuffer(); + String loggerName = record.getLoggerName(); + if (useLoggerName) { + if (loggerName != null) { + message.append("("); + message.append(record.getLoggerName()); + message.append(") "); + } + } else if (useShortLoggerName) { + if (loggerName != null) { + message.append("("); + int lastDot = loggerName.lastIndexOf('.'); + if (lastDot >= 0) + loggerName = loggerName.substring( + lastDot + 1); + message.append(loggerName); + message.append(") "); + } + } + + message.append(record.getMessage()); + + /* + * If the Severity is null, it's not meant to be logged + * via syslog. + */ + if (record.getThrown() != null && useStackTraces == true) { + /* + * Format the stack trace as one line and tack + * it onto the message. + */ + message.append(" "); + message.append(SuccinctStackTraceFormatter + .formatWithDescription(record.getThrown(), + "with tracing information: ").toString()); + } + syslog(severity.getNative(), message.toString()); + } + + public void flush() + { + } + + public void close() throws SecurityException + { + if (instance != null) { + closelog(); + instance = null; + } + } + + /** + * Formatters may not be used with SyslogHandler. + * + * @throws IllegalArgumentException if the use of one is + * attempted. + */ + public void setFormatter(Formatter formatter) + { + throw new IllegalArgumentException(); + } + + /** + * Returns the <code>syslog(3C)</code> ident string, which is + * prepended to every message. + */ + public String getIdent() + { + return (ident); + } + + /** + * Returns the <code>syslog</code> facility to be logged to. + */ + public Facility getFacility() + { + return (facility); + } + +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/SysloglikeFormatter.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/SysloglikeFormatter.java new file mode 100644 index 0000000000..27d9236e49 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/SysloglikeFormatter.java @@ -0,0 +1,172 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* ident "%Z%%M% %I% %E% SMI" */ + +package com.sun.solaris.service.logging; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.*; +import java.util.*; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; + +import com.sun.solaris.service.exception.SuccinctStackTraceFormatter; + +/** + * Formats a LogRecord in a human-readable, <code>syslog</code>-like + * format, and is intended for use with non-syslog handlers, such as + * FileHandler. + * + * Multi-line messages are automatically indented by four spaces to make + * subsequent lines easier to differentiate from new records. + */ +public class SysloglikeFormatter extends Formatter { + /** + * The date set for each published Record. + */ + private Date date = new Date(); + + /** + * Format string for published dates. + */ + private final static String dateFormat = + "MMM d kk:mm:ss"; + + /** + * For published dates, the formatter. + */ + private DateFormat dateFormatter; + + /** + * For published dates, the argument to date formatter. + */ + private Object args[] = { date }; + + /** + * Line separator string. + */ + private String lineSeparator = (String)java.security.AccessController + .doPrivileged(new sun.security.action.GetPropertyAction( + "line.separator")); + + /** + * Flag to set whether log records should indicate the name of + * the class generating the record, if possible. (default + * false) + */ + private boolean useClassName = false; + + /** + * Flag to set whether log records should indicate the record's + * logger, if useClassName isn't set and the class name was + * available. (default false) + */ + private boolean useLoggerName = false; + + /** + * Flag to set whether log records should indicate the last + * component of the record's logger name, if useLoggerName isn't + * set. (default true) + */ + private boolean useShortLoggerName = true; + + /** + * Flag to set whether log records should indicate the method + * used to invoke the logger, if available. (default false) + */ + private boolean useMethodName = false; + + /** + * Flag to set whether each record should be split into two + * lines such that the severity and message are on a line by + * themselves. (default false) + */ + private boolean useTwoLineStyle = false; + + /** + * Format the given LogRecord. + * @param record the log record to be formatted. + * @return a formatted log record. + */ + public synchronized String format(LogRecord record) + { + StringBuffer sb = new StringBuffer(); + + date.setTime(record.getMillis()); + StringBuffer text = new StringBuffer(); + if (dateFormatter == null) + dateFormatter = new SimpleDateFormat(dateFormat); + sb.append(dateFormatter.format(date)); + + if (record.getSourceClassName() != null && useClassName) { + sb.append(" "); + sb.append(record.getSourceClassName()); + } else if (useLoggerName) { + if (record.getLoggerName() != null) { + sb.append(" "); + sb.append(record.getLoggerName()); + } + } else if (useShortLoggerName) { + String loggerName = record.getLoggerName(); + + if (loggerName != null) { + sb.append(" "); + int lastDot = loggerName.lastIndexOf('.'); + if (lastDot >= 0) + loggerName = loggerName.substring( + lastDot + 1); + sb.append(loggerName); + } + } + + if (record.getSourceMethodName() != null && useMethodName) { + sb.append(" "); + sb.append(record.getSourceMethodName()); + } + if (useTwoLineStyle) + sb.append(lineSeparator); + else + sb.append(" "); + + String message = formatMessage(record); + message = message.replaceAll("\n", lineSeparator + " "); + + sb.append(record.getLevel()).toString(); + sb.append(": "); + sb.append(message); + if (record.getThrown() != null) { + sb.append(" "); + sb.append(SuccinctStackTraceFormatter + .formatWithDescription(record.getThrown(), + "with tracing information: ").toString()); + } + sb.append(lineSeparator); + + return sb.toString(); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/package.html new file mode 100644 index 0000000000..4224cf5b45 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/logging/package.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +Extends the logging API for use with syslog(3C). + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2002/287/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, +please see: +<ul> + <li><a href="http://taxman.eng/projects/dynamic-resource-pools/">Dynamic Resource Pools Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Component.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Component.java new file mode 100644 index 0000000000..ff762d83ed --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Component.java @@ -0,0 +1,186 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +/** + * The <code>Component</code> class represents a configuration + * resource component. + */ +public class Component extends Element +{ + /** + * The type of the component. + */ + private final String type; + + /** + * The system id of the component. + */ + private final long sys_id; + + /** + * The key of the component. + */ + private final String key; + + /** + * Constructor + * + * @param conf The configuration to which this component belongs + * @param comp The pointer to the native component + * @throws PoolsException If accessing the proxy fails. + */ + Component(Configuration conf, long comp) throws PoolsException + { + _conf = conf; + Value val = getProperty("type", comp); + type = val.getString(); + val.close(); + val = getProperty(type + ".sys_id", comp); + sys_id = val.getLong(); + val.close(); + key = type + "." + sys_id; + } + + /** + * Return the pointer to the component represented by this object. + * + * @return conf the pointer to the component represented by this object + * @throws PoolsException If the component cannot be located. + */ + long getComponent() throws PoolsException + { + return (_conf.checkComponent(type, sys_id)); + } + + /** + * Returns a descriptive string which describes the component. + * + * @param deep Whether the information should contain information about + * all contained elements. + * @throws PoolsException If the component cannot be located. + * @return a descriptive string which describes the component. + */ + public String getInformation(int deep) throws PoolsException + { + return (PoolInternal.pool_component_info(_conf.getConf(), + getComponent(), deep)); + } + + /** + * Returns a string representation of this component. + * + * @return a string representation of this component. + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + + buf.append(type); + buf.append(" "); + buf.append(sys_id); + return (buf.toString()); + } + + /** + * Indicates whether some other Component is "equal to this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof Component)) + return (false); + Component other = (Component) o; + if (type.compareTo(other.getType()) != 0 || + sys_id != other.getSysId()) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (type.hashCode() + (int) sys_id); + } + + /** + * Return the pointer to this component as an element. + * + * @return The pointer to the native component which this object wraps. + * @throws PoolsExecption If there is an error converting the native + * component pointer to a native elem pointer. + */ + protected long getElem() throws PoolsException + { + long elem; + + if ((elem = PoolInternal.pool_component_to_elem(_conf.getConf(), + getComponent())) == 0) + throw new PoolsException(); + return (elem); + } + + /** + * Return the type of the component + */ + String getType() + { + return (type); + } + + /** + * Return the system id of the component. + */ + long getSysId() + { + return (sys_id); + } + + /** + * Return the key of the component. + */ + String getKey() + { + return (key); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Configuration.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Configuration.java new file mode 100644 index 0000000000..ade169e78e --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Configuration.java @@ -0,0 +1,689 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; + +/** + * The <code>Configuration</code> class represents a pools configuration. + */ +public class Configuration extends Element +{ + /** + * Indicates whether the configuration represents a usable + * configuration. + */ + private boolean _valid = false; + + /** + * A reference to the native libpool object represented by + * this instance. + */ + private long _this; + + /** + * The name of this instance. + */ + private String name; + + /** + * The cache of elements known to this configuration. + */ + private Map elements; + + /** + * The key of the configuration. + */ + private String key; + + /** + * Constructor + * @param location The location of the configuration. + * @param perms The OR'd permissions used when opening this + * configuration. + * @exception PoolsException The error message generated by + * libpool. + */ + public Configuration(String location, int perms) throws PoolsException + { + if (((_this = PoolInternal.pool_conf_alloc())) == 0) + throw new PoolsException(); + _conf = this; + open(location, perms); + elements = new HashMap(); + } + + /** + * Reclaim the memory allocated for this configuration by the C + * proxy. + * + * @throws Throwable If freeing this configuration fails. + */ + protected void finalize() throws Throwable + { + try + { + close(); + if (_this != 0) { + PoolInternal.pool_conf_free(_this); + _this = 0; + } + } + finally + { + super.finalize(); + } + } + + /** + * Returns a pointer to the native configuration, wrapped by this + * instance. + * + * @return the configuration pointer. + */ + final long getConf() + { + return (_this); + } + + /** + * Opens the configuration at the supplied location and with the + * supplied permissions. + * + * @throws PoolsException if there is an error opening the + * configuration. + */ + public void open(String location, int perms) throws PoolsException + { + if (_valid == false) { + if (PoolInternal.pool_conf_open(getConf(), location, + perms) != PoolInternal.PO_SUCCESS) { + throw new PoolsException(); + } + _valid = true; + name = getStringProperty("system.name"); + key = "system." + name; + } + } + + /** + * Closes the configuration. + * + */ + public void close() + { + if (_valid == true) { + elements.clear(); + PoolInternal.pool_conf_close(getConf()); + name = key = null; + } + _valid = false; + } + + /** + * Returns the location of the configuration. + * + * @return the location of the configuration. + */ + public String getLocation() + { + return (PoolInternal.pool_conf_location(getConf())); + } + + /** + * Returns the status of the configuration. + * + * @return the status of the configuration. + */ + public int status() + { + return (PoolInternal.pool_conf_status(getConf())); + } + + /** + * Remove the configuration. + * + * @throws PoolsExecption If the removal fails. + */ + public void remove() throws PoolsException + { + if (PoolInternal.pool_conf_remove(getConf()) != + PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Rollback the configuration, undoing any changes which have been + * made since the last commit or (if there are no commits) since the + * configuration was opened. + * + * @throws PoolsExecption If the rollback fails. + */ + public void rollback() throws PoolsException + { + if (PoolInternal.pool_conf_rollback(getConf()) != + PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Commit the configuration, making any changes since the configuration + * was last committed (or opened if there have been no prior commits) + * permanent. + * + * @throws PoolsExecption If the commit fails. + */ + public void commit(int active) throws PoolsException + { + if (PoolInternal.pool_conf_commit(getConf(), active) != + PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Export the configuration, storing the current state of the + * configuration at the supplied location in the supplied format. + * + * @param location The location of the export. + * @param format The format of the export. + * @throws PoolsExecption If the export fails. + */ + public void export(String location, int format) throws PoolsException + { + if (PoolInternal.pool_conf_export(getConf(), location, format) + != PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Validate the configuration, ensuring that the current state of the + * configuration satisfies the supplied validation level. + * + * @param level The desired level of validation. + * @throws PoolsExecption If the validation fails. + */ + public void validate(int level) throws PoolsException + { + if (PoolInternal.pool_conf_validate(getConf(), level) + != PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Update the configuration, ensuring that the current state of the + * configuration reflects that of the kernel. + * + * @throws PoolsExecption If the update fails. + * @return a bitmap of the changed types. + */ + public int update() throws PoolsException + { + return (PoolInternal.pool_conf_update(getConf())); + } + + /** + * Create a pool with the supplied name. + * + * @param name The name of the PoolInternal. + * @throws PoolsExecption If the pool creation fails. + * @return a pool with the supplied name. + */ + public Pool createPool(String name) throws PoolsException + { + long aPool; + + if ((aPool = PoolInternal.pool_create(getConf(), name)) == 0) { + throw new PoolsException(); + } + Pool p = new Pool(this, aPool); + elements.put(p.getKey(), p); + return (p); + } + + /** + * Destroy the supplied PoolInternal. + * + * @param aPool The pool to be destroyed. + * @throws PoolsException If the pool cannot be located. + */ + public void destroyPool(Pool aPool) throws PoolsException + { + elements.remove(aPool.getKey()); + PoolInternal.pool_destroy(getConf(), aPool.getPool()); + } + + /** + * Get the pool with the supplied name. + * + * @param name The name of the pool to be found. + * @throws PoolsExecption If the pool cannot be located. + * @return a pool with the supplied name. + */ + public Pool getPool(String name) throws PoolsException + { + long aPool; + + if ((aPool = PoolInternal.pool_get_pool(getConf(), name)) == + 0) { + throw new PoolsException(); + } + if (elements.containsKey("PoolInternal." + name)) + return ((Pool) elements.get("PoolInternal." + name)); + else { + Pool p = new Pool(this, aPool); + elements.put(p.getKey(), p); + return (p); + } + } + + /** + * Get the proxy for the pool with the supplied name. + * + * @param name The name of the pool to be found. + * @throws PoolsExecption If the pool cannot be located. + * @return the proxy for the pool with the supplied name. + */ + long checkPool(String name) throws PoolsException + { + long aPool; + + if ((aPool = PoolInternal.pool_get_pool(getConf(), name)) == + 0) { + throw new PoolsException(); + } + return (aPool); + } + + /** + * Get a list of pools which match the supplied selection criteria + * in values. + * + * @param values A list of values to be used to qualify the search. + * @throws PoolsExecption If there is an error executing the query. + * @return a list of pools which match the supplied criteria + */ + public List getPools(List values) throws PoolsException + { + List pools; + + if ((pools = PoolInternal.pool_query_pools(getConf(), values)) + == null) { + if (PoolInternal.pool_error() == 0 || + PoolInternal.pool_error() == + PoolInternal.POE_INVALID_SEARCH) + return new ArrayList(); + else + throw new PoolsException(); + } + ArrayList aList = new ArrayList(pools.size()); + for (int i = 0; i < pools.size(); i++) + aList.add(new Pool(this, + ((Long)pools.get(i)).longValue())); + return (aList); + } + + /** + * Create a resource with the supplied type and name. + * + * @param type The type of the resource. + * @param name The name of the resource. + * @throws PoolsExecption If the resource creation fails. + * @return a resource of the supplied type and name. + */ + public Resource createResource(String type, String name) + throws PoolsException + { + long aResource; + + if ((aResource = PoolInternal.pool_resource_create(getConf(), + type, name)) == 0) { + throw new PoolsException(); + } + Resource res = new Resource(this, aResource); + elements.put(res.getKey(), res); + return (res); + } + + /** + * Destroy the supplied resource. + * + * @param res The resource to be destroyed. + * @throws PoolsException If the resource cannot be located. + */ + public void destroyResource(Resource res) throws PoolsException + { + elements.remove(res.getKey()); + PoolInternal.pool_resource_destroy(getConf(), + res.getResource()); + } + + /** + * Get the resource with the supplied name. + * + * @param type The type of the resource to be found. + * @param name The name of the resource to be found. + * @throws PoolsExecption If the resource cannot be located. + * @return a resource with the supplied name. + */ + public Resource getResource(String type, String name) + throws PoolsException + { + long res; + + if ((res = PoolInternal.pool_get_resource(getConf(), type, + name)) == 0) { + throw new PoolsException(); + } + if (elements.containsKey(type + "." + name)) + return ((Resource) elements.get(type + "." + name)); + else { + Resource r = new Resource(this, res); + elements.put(r.getKey(), r); + return (r); + } + } + + /** + * Get the proxy for the resource with the supplied type and + * name. + * + * @param type The type of the resource to be found. + * @param name The name of the resource to be found. + * @throws PoolsExecption If the resource cannot be located. + * @return the proxy for the resource with the supplied name. + */ + long checkResource(String type, String name) throws PoolsException + { + long res; + + if ((res = PoolInternal.pool_get_resource(getConf(), type, + name)) == 0) { + throw new PoolsException(); + } + return (res); + } + + /** + * Get a list of resources which match the supplied selection criteria + * in values. + * + * @param values A list of values to be used to qualify the search. + * @throws PoolsExecption If there is an error executing the query. + * @return a list of resources which match the supplied criteria + */ + public List getResources(List values) throws PoolsException + { + List resources; + + if ((resources = PoolInternal.pool_query_resources(getConf(), + values)) == null) { + if (PoolInternal.pool_error() == 0 || + PoolInternal.pool_error() == + PoolInternal.POE_INVALID_SEARCH) + return new ArrayList(); + else + throw new PoolsException(); + } + ArrayList aList = new ArrayList(resources.size()); + for (int i = 0; i < resources.size(); i++) + aList.add(new Resource(this, + ((Long)resources.get(i)).longValue())); + return (aList); + } + + /** + * Get the component with the supplied name. + * + * @param type The type of the component to be found. + * @param sys_id The sys_id of the component to be found. + * @throws PoolsExecption If the component cannot be located. + * @return a component with the supplied name. + */ + public Component getComponent(String type, long sys_id) + throws PoolsException + { + List props = new ArrayList(); + Value ptype = new Value("type", type); + Value psys_id = new Value(type + ".sys_id", sys_id); + + props.add(ptype); + props.add(psys_id); + List comps = getComponents(props); + ptype.close(); + psys_id.close(); + if (comps.size() != 1) + throw new PoolsException(); + return ((Component) comps.get(0)); + } + + /** + * Get the component proxy with the supplied type and sys_id. + * + * @param type The type of the component to be found. + * @param sys_id The sys_id of the component to be found. + * @throws PoolsExecption If the component cannot be located. + * @return a component with the supplied name. + */ + long checkComponent(String type, long sys_id) + throws PoolsException + { + List props = new ArrayList(); + Value ptype = new Value("type", type); + Value psys_id = new Value(type + ".sys_id", sys_id); + + props.add(ptype); + props.add(psys_id); + List comps = checkComponents(props); + ptype.close(); + psys_id.close(); + if (comps.size() != 1) + throw new PoolsException(); + return (((Long)comps.get(0)).longValue()); + } + + /** + * Get a list of components which match the supplied selection criteria + * in values. + * + * @param values A list of values to be used to qualify the search. + * @throws PoolsExecption If there is an error executing the query. + * @return a list of components which match the supplied criteria + */ + public List getComponents(List values) throws PoolsException + { + List components; + + if ((components = PoolInternal.pool_query_components(getConf(), + values)) == null) { + if (PoolInternal.pool_error() == 0 || + PoolInternal.pool_error() == + PoolInternal.POE_INVALID_SEARCH) + return new ArrayList(); + else + throw new PoolsException(); + } + ArrayList aList = new ArrayList(components.size()); + for (int i = 0; i < components.size(); i++) { + /* + * Extract type information + */ + Value typeVal = new Value(name); + + if (PoolInternal.pool_get_property(getConf(), + ((Long)components.get(i)).longValue(), "type", + typeVal.getValue()) == PoolInternal.POC_INVAL) + throw new PoolsException(); + if (typeVal == null) + throw new PoolsException(); + String type = typeVal.getString(); + typeVal.close(); + + Value idValue = new Value(name); + + if (PoolInternal.pool_get_property(getConf(), + ((Long)components.get(i)).longValue(), + type + ".sys_id", idValue.getValue()) == + PoolInternal.POC_INVAL) + throw new PoolsException(); + if (idValue == null) + throw new PoolsException(); + long sys_id = idValue.getLong(); + idValue.close(); + + if (elements.containsKey(type + "." + sys_id)) + aList.add((Component)elements.get(type + "." + + sys_id)); + else + aList.add(new Component(this, ((Long)components. + get(i)).longValue())); + } + return (aList); + + } + + /** + * Get a list of component proxies which match the supplied + * selection criteria in values. + * + * @param values A list of values to be used to qualify the search. + * @throws PoolsExecption If there is an error executing the query. + * @return a list of component proxies which match the + * supplied criteria + */ + List checkComponents(List values) throws PoolsException + { + List components; + + if ((components = PoolInternal.pool_query_components(getConf(), + values)) == null) { + if (PoolInternal.pool_error() == 0 || + PoolInternal.pool_error() == + PoolInternal.POE_INVALID_SEARCH) + return new ArrayList(); + else + throw new PoolsException(); + } + return (components); + } + /** + * Returns a descriptive string which describes the configuration. + * + * @param deep Whether the information should contain information about + * all contained elements. + * @return a descriptive string which describes the configuration. + */ + public String getInformation(int deep) + { + return (PoolInternal.pool_conf_info(_conf.getConf(), deep)); + } + + /** + * Returns a string representation of this configuration. + * + * @return a string representation of this configuration. + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + + buf.append("system: "); + buf.append(name); + return (buf.toString()); + } + + /** + * Indicates whether some other Configuration is "equal to this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof Configuration)) + return (false); + Configuration other = (Configuration) o; + if (name.compareTo(other.getName()) != 0) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return name.hashCode(); + } + + /** + * Return the pointer to this configuration as an element. + * + * @return The pointer to the native configuration which this object + * wraps. + * @throws PoolsExecption If there is an error converting the native + * configuration pointer to a native elem pointer. + */ + protected long getElem() throws PoolsException + { + long elem; + + if ((elem = PoolInternal.pool_conf_to_elem(getConf())) == 0) + throw new PoolsException(); + return (elem); + } + + /** + * Return the anme of the configuration. + */ + String getName() + { + return (name); + } + + /** + * Return the key of the configuration. + */ + String getKey() + { + return (key); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Element.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Element.java new file mode 100644 index 0000000000..8736fd6c8e --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Element.java @@ -0,0 +1,287 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +import java.util.List; +import java.util.ArrayList; + +/** + * The <code>Element</code> class represents a pools configuration + * element. The class is an abstract, base class for concrete + * implementation elements, such as pool and resource. + */ +public abstract class Element implements Property, PropertyWalk +{ + /** + * The configuration to which this element belongs. + */ + protected Configuration _conf; + + /** + * Returns a string representation of this element. + * + * @return a string representation of this element. + */ + public String toString() + { + try { + return (getInformation(1)); + } catch (PoolsException pe) { + return (pe.toString()); + } + } + + /** + * Returns a descriptive string which describes the element. + * + * @param deep Whether the information should contain information about + * all contained elements. + * @throws PoolsException If the element cannot be located. + * @return a descriptive string which describes the element. + */ + public abstract String getInformation(int deep) throws PoolsException; + + /** + * Get the property with the supplied name. + * + * @param name The name of the property to be retrieved. + * @throws PoolsExecption If there is an error accessing the property. + * @return a value containing the property details. + */ + private Value getProperty(String name) throws PoolsException + { + Value value = new Value(name); + + if (PoolInternal.pool_get_property(_conf.getConf(), getElem(), + name, value.getValue()) == PoolInternal.POC_INVAL) + throw new PoolsException(); + return (value); + } + + /** + * Get the property with the supplied name using the supplied + * proxy. + * + * @param name The name of the property to be retrieved. + * @param proxy The proxy item used to retrieve the property. + * @throws PoolsExecption If there is an error accessing the property. + * @return a value containing the property details. + */ + protected Value getProperty(String name, long proxy) + throws PoolsException + { + Value value = new Value(name); + + if (PoolInternal.pool_get_property(_conf.getConf(), proxy, name, + value.getValue()) == PoolInternal.POC_INVAL) + throw new PoolsException(); + return (value); + } + + /** + * Put the supplied value as an element property with the supplied + * name. + * + * @param name The name of the property to be updated. + * @param value The value of the property to be updated. + * @throws PoolsExecption If there is an error accessing the property. + */ + public void putProperty(String name, Value value) throws PoolsException + { + if (PoolInternal.pool_put_property(_conf.getConf(), getElem(), + name, value.getValue()) != PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Remove the element property with the supplied name. + * + * @param name The name of the property to be removed. + * @throws PoolsExecption If there is an error removing the property. + */ + public void rmProperty(String name) throws PoolsException + { + if (PoolInternal.pool_rm_property(_conf.getConf(), getElem(), + name) != PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Get a String property. + * + * If the type of the property does not match, i.e. it's not a + * String, or the element does not have such a property then a + * PoolsException is thrown. + * + * @param name The name of the property to be retrieved. + * @throws PoolsException If getting the String property fails. + */ + public String getStringProperty(String name) throws PoolsException + { + Value val = getProperty(name); + + if (val != null) { + String ret = val.getString(); + val.close(); + return (ret); + } + throw new PoolsException(); + } + + /** + * Get a long property. + * + * If the type of the property does not match, i.e. it's not a + * long, or the element does not have such a property then a + * PoolsException is thrown. + * + * @param name The name of the property to be retrieved. + * @throws PoolsException If getting the long property fails. + */ + public long getLongProperty(String name) throws PoolsException + { + Value val = getProperty(name); + + if (val != null) { + long ret = val.getLong(); + val.close(); + return (ret); + } + throw new PoolsException(); + } + + /** + * Get a double property. + * + * If the type of the property does not match, i.e. it's not a + * double, or the element does not have such a property then a + * PoolsException is thrown. + * + * @param name The name of the property to be retrieved. + * @throws PoolsException If getting the double property fails. + */ + public double getDoubleProperty(String name) throws PoolsException + { + Value val = getProperty(name); + + if (val != null) { + double ret = val.getDouble(); + val.close(); + return (ret); + } + throw new PoolsException(); + } + + /** + * Get a boolean property. + * + * If the type of the property does not match, i.e. it's not a + * boolean, or the element does not have such a property then + * a PoolsException is thrown. + * + * @param name The name of the property to be retrieved. + * @throws PoolsException If getting the boolean property fails. + */ + public boolean getBoolProperty(String name) throws PoolsException + { + Value val = getProperty(name); + + if (val != null) { + boolean ret = val.getBool(); + val.close(); + return (ret); + } + throw new PoolsException(); + } + + /** + * Walk all properties of the invoking object. + * + * @param elem The element to whom the property belongs. + * @param val The value representing the current element. + * @param user User supplied data, provided when the walk is invoked. + * @throws PoolsExecption If there is an error walking the property. + * @return 0 to continue the walk, anything else to terminate it. + */ + public int walk(Element elem, Value val, Object user) + throws PoolsException + { + System.out.println("Property name: " + val.getName() + + ", value: "+val.toString()); + val.close(); + return (0); + } + + /** + * Return the pointer to this subtype as an element. + * + * @return The pointer to the native subtype which this object wraps. + * @throws PoolsExecption If there is an error converting the native + * subtype pointer to a native elem pointer. + */ + protected abstract long getElem() throws PoolsException; + + /** + * Walk all the properties of this element. + * + * @param handler The object which will receive the callbacks. + * @param user Data supplied by the user for use in the callback. + * @return 0 for a successful walk, else 1. + * @throws PoolsExecption If there is an error during the walk. + */ + public int walkProperties(PropertyWalk handler, Object user) + throws PoolsException + { + return (walkProps(_conf.getConf(), getElem(), handler, user)); + } + + /** + * Walk the properties of the supplied element using the + * supplied handler. + * + * @param conf native reference to the configuration in which + * the element belongs. + * @param elem native reference to the element whose + * properties are to be walked. + * @param handler a method to be invoked with each property of + * the elem. + * @param user a user parameter which is passed to handler on + * each invocation. + * @throws PoolsException if there is an error accessing the + * element properties. + */ + private native int walkProps(long conf, long elem, + PropertyWalk handler, Object user) throws PoolsException; + + /** + * Return the key of the element. + */ + abstract String getKey(); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/HRTime.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/HRTime.java new file mode 100644 index 0000000000..0cab0c6f71 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/HRTime.java @@ -0,0 +1,107 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.pools; + +import java.math.BigInteger; +import java.lang.Comparable; + +/** + * hrtime_t-like (see gethrtime(3C)) uptime-based time value (i.e., resilient + * to changes to the host's clock) for comparison of timestamps of sampled + * data. + */ +public class HRTime implements Comparable { + /** + * The native <code>hrtime_t</code> value. + */ + private UnsignedInt64 value; + + /** + * Constructor. + */ + public HRTime() + { + this.value = timestamp(); + } + + /** + * Constructs a new HRTime with the value of the given + * UnsignedInt64. + * + * @param value The timestamp to be used. + */ + public HRTime(UnsignedInt64 value) + { + this.value = value; + } + + /** + * Computes the difference between this time and another, older, + * time. + * + * @param older the time from which to compute the delta. + * @throws IllegalArgumentException if the given time is not + * earlier than this one. + */ + public HRTime deltaFrom(HRTime older) + { + if (older.compareTo(value) > 0) + throw(new IllegalArgumentException()); + else + return (new HRTime(new UnsignedInt64(value + .subtract(older.getValue())))); + } + + /** + * Returns this HRTime's value. + */ + public UnsignedInt64 getValue() + { + return (value); + } + + /** + * Return a string representation of this instance. + */ + public String toString() + { + return (value.toString()); + } + + public int compareTo(Object o) { + HRTime other = (HRTime) o; + + return (value.compareTo(other.getValue())); + } + + /** + * Return the current timestamp. + */ + private native UnsignedInt64 timestamp(); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Makefile new file mode 100644 index 0000000000..ab5fdcf0e1 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Makefile @@ -0,0 +1,59 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/service/pools/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + + +SOURCE = PoolInternal.java \ + Component.java \ + Configuration.java \ + Element.java \ + HRTime.java \ + Property.java \ + PropertyWalk.java \ + Pool.java \ + PoolsException.java \ + Resource.java \ + UnsignedInt64.java \ + Value.java + +all install: $(SOURCE:.java=.class) + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Pool.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Pool.java new file mode 100644 index 0000000000..f22f4b311f --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Pool.java @@ -0,0 +1,227 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +import java.util.List; +import java.util.ArrayList; + +/** + * The <code>Pool</code> class represents a Resource Pool. + */ +public class Pool extends Element { + + /** + * The name of this instance. + */ + private final String name; + /** + * The key of the pool. + */ + private final String key; + + /** + * Constructor + * @param conf The configuration to which this pool belongs. + * @param pool The pointer to the native pool which this object wraps. + * @throws PoolsException If accessing the proxy fails. + */ + Pool(Configuration conf, long pool) throws PoolsException + { + _conf = conf; + Value val = getProperty("pool.name", pool); + name = val.getString(); + val.close(); + key = "pool." + name; + } + + /** + * Returns a pointer to the native pool represented by this + * pool object. + * + * @throws PoolsException If the pool cannot be located. + * @return a pointer to the native pool represented by this + * pool object. + */ + long getPool() throws PoolsException + { + return (_conf.checkPool(name)); + } + + /** + * Associate this pool with the supplied resource. + * + * @param res A resource in the same configuration as this pool. + * @throws PoolsException If there is an error whilst associating the + * resource with the pool. + */ + public void associate(Resource res) throws PoolsException + { + if (PoolInternal.pool_associate(_conf.getConf(), getPool(), + res.getResource()) != PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Dissociate this pool from the supplied resource. + * + * @param res A resource in the same configuration as this pool. + * @throws PoolsException If there is an error whilst dissociating the + * resource from the pool. + */ + public void dissociate(Resource res) throws PoolsException + { + if (PoolInternal.pool_dissociate(_conf.getConf(), getPool(), + res.getResource()) != PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Get a list of resources which match the supplied selection criteria + * in values. Only resources which are associated with this pool are + * searched. + * + * @param values A list of values to be used to qualify the search. + * @throws PoolsExecption If there is an error executing the query. + * @return a list of resources which match the supplied criteria + */ + public List getResources(List values) throws PoolsException + { + List resources; + + if ((resources = PoolInternal.pool_query_pool_resources( + _conf.getConf(), getPool(), values)) == null) { + if (PoolInternal.pool_error() == 0 || + PoolInternal.pool_error() == + PoolInternal.POE_INVALID_SEARCH) + return new ArrayList(); + else + throw new PoolsException(); + } + ArrayList aList = new ArrayList(resources.size()); + for (int i = 0; i < resources.size(); i++) + aList.add(new Resource(_conf, + ((Long)resources.get(i)).longValue())); + return (aList); + } + + /** + * Returns a descriptive string which describes the pool. + * + * @param deep Whether the information should contain information about + * all contained elements. + * @throws PoolsException If the pool cannot be located. + * @return a descriptive string which describes the pool. + */ + public String getInformation(int deep) throws PoolsException + { + return (PoolInternal.pool_info(_conf.getConf(), getPool(), + deep)); + } + + /** + * Returns a string representation of this pool. + * + * @return a string representation of this pool. + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + + buf.append("pool: "); + buf.append(name); + return (buf.toString()); + } + + /** + * Indicates whether some other Pool is "equal to this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof Pool)) + return (false); + Pool other = (Pool) o; + if (name.compareTo(other.getName()) != 0) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (name.hashCode()); + } + + /** + * Return the pointer to this pool as an element. + * + * @return The pointer to the native pool which this object wraps. + * @throws PoolsExecption If there is an error converting the native + * pool pointer to a native elem pointer. + */ + protected long getElem() throws PoolsException + { + long elem; + + if ((elem = PoolInternal.pool_to_elem(_conf.getConf(), + getPool())) == 0) + throw new PoolsException(); + return (elem); + } + + /** + * Return the name of the pool. + */ + String getName() + { + return (name); + } + + /** + * Return the key of the pool. + */ + String getKey() + { + return (key); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PoolInternal.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PoolInternal.java new file mode 100644 index 0000000000..d230414070 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PoolInternal.java @@ -0,0 +1,207 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.pools; + +/** + * A thin layer over the libpool(3LIB) interface so that Java can be + * used to manipulate resource pools. For more information on this + * facility refer to the manpage and the developer documentation. + * + * Most of the functionality in this class is not intended to be + * exposed to users of the package. The other classes in the package + * provide appropriate Java abstractions for using this functionality. + * + * Refer to the package documentation and the documentation of the + * other publicly visible classes for more details. + */ +public class PoolInternal { + static { + System.loadLibrary("jpool"); + PoolInternal.init(); + } + + final static native void init(); + final static native long pool_version(long ver); + final static native int get_POX_NATIVE(); + final static native int get_POX_TEXT(); + final static native int get_POC_INVAL(); + final static native int get_POC_UINT(); + final static native int get_POC_INT(); + final static native int get_POC_DOUBLE(); + final static native int get_POC_BOOL(); + final static native int get_POC_STRING(); + final static native int get_POV_NONE(); + final static native int get_POV_LOOSE(); + final static native int get_POV_STRICT(); + final static native int get_POV_RUNTIME(); + final static native int get_POF_INVALID(); + final static native int get_POF_VALID(); + final static native int get_POF_DESTROY(); + public final static native int pool_error(); + public final static native String pool_strerror(int error); + public final static native String pool_strerror_sys(); + public final static native int pool_resource_type_list(long types, + long numtypes); + public final static native int pool_get_status(long state); + public final static native int pool_set_status(int state); + final static native long pool_conf_alloc(); + final static native void pool_conf_free(long conf); + final static native int pool_conf_status(long conf); + final static native int pool_conf_close(long conf); + final static native int pool_conf_remove(long conf); + final static native int pool_conf_open(long conf, String location, + int oflags); + final static native int pool_conf_rollback(long conf); + final static native int pool_conf_commit(long conf, int active); + final static native int pool_conf_export(long conf, String location, + int fmt); + final static native int pool_conf_validate(long conf, int level); + final static native int pool_conf_update(long conf); + final static native long pool_get_pool(long conf, String name); + final static native java.util.List pool_query_pools(long conf, + java.util.List props); + final static native long pool_get_resource(long conf, String type, + String name); + final static native java.util.List pool_query_resources(long conf, + java.util.List props); + final static native java.util.List pool_query_components(long conf, + java.util.List props); + final static native String pool_conf_location(long conf); + final static native String pool_conf_info(long conf, int deep); + final static native long pool_resource_create(long conf, + String type, String name); + final static native int pool_resource_destroy(long conf, long res); + final static native int pool_resource_transfer(long conf, + long src, long tgt, long size); + final static native int pool_resource_xtransfer(long conf, + long src, long tgt, java.util.List components); + final static native java.util.List pool_query_resource_components( + long conf, long res, java.util.List props); + final static native String pool_resource_info(long conf, long res, + int deep); + final static native long pool_create(long conf, String name); + final static native int pool_destroy(long conf, long pool); + final static native int pool_associate(long conf, long pool, + long res); + final static native int pool_dissociate(long conf, long pool, + long res); + final static native String pool_info(long conf, long pool, int deep); + final static native java.util.List pool_query_pool_resources( + long conf, long pool, java.util.List props); + final static native long pool_get_owning_resource(long conf, + long comp); + final static native String pool_component_info(long conf, + long comp, int deep); + final static native int pool_get_property(long conf, long elem, + String name, long val); + final static native int pool_put_property(long conf, long elem, + String name, long val); + final static native int pool_rm_property(long conf, long elem, + String name); + final static native int pool_walk_properties(long conf, long elem, + long user, long callback); + final static native long pool_conf_to_elem(long conf); + final static native long pool_to_elem(long conf, long pool); + final static native long pool_resource_to_elem(long conf, long res); + final static native long pool_component_to_elem(long conf, long comp); + final static native int pool_value_get_uint64(long pv, long result); + final static native int pool_value_get_int64(long pv, long result); + final static native int pool_value_get_double(long pv, long result); + final static native int pool_value_get_bool(long pv, long result); + final static native int pool_value_get_string(long pv, long result); + final static native int pool_value_get_type(long pv); + final static native void pool_value_set_uint64(long pv, long val); + final static native void pool_value_set_int64(long pv, long val); + final static native void pool_value_set_double(long pv, double val); + final static native void pool_value_set_bool(long pv, short val); + final static native int pool_value_set_string(long pv, String val); + final static native String pool_value_get_name(long pv); + final static native int pool_value_set_name(long pv, String val); + final static native long pool_value_alloc(); + final static native void pool_value_free(long pv); + public final static native String pool_static_location(); + public final static native String pool_dynamic_location(); + public final static native int pool_set_binding(String name, + int idtype, int id); + public final static native String pool_get_binding(int pid); + public final static native String pool_get_resource_binding( + String type, int pid); + final static native int pool_walk_pools(long conf, long user, + long callback); + final static native int pool_walk_resources(long conf, long pool, + long user, long callback); + final static native int pool_walk_components(long conf, long res, + long user, long callback); + /* + * enums and constants + */ + public final static int POOL_VER_CURRENT = 1; + public final static int POOL_VER_NONE = 0; + public final static int PO_TRUE = 1; + public final static int PO_FALSE = 0; + public final static int PO_SUCCESS = 0; + public final static int PO_FAIL = -1; + public final static int POE_OK = 0; + public final static int POE_BAD_PROP_TYPE = 1; + public final static int POE_INVALID_CONF = 2; + public final static int POE_NOTSUP = 3; + public final static int POE_INVALID_SEARCH = 4; + public final static int POE_BADPARAM = 5; + public final static int POE_PUTPROP = 6; + public final static int POE_DATASTORE = 7; + public final static int POE_SYSTEM = 8; + public final static int POE_ACCESS = 9; + public final static int PO_RDONLY = 0x0; + public final static int PO_RDWR = 0x1; + public final static int PO_CREAT = 0x2; + public final static int PO_DISCO = 0x4; + public final static int PO_UPDATE = 0x8; + public final static String POA_IMPORTANCE = "importance based"; + public final static String POA_SURPLUS_TO_DEFAULT = + "surplus to default"; + public final static int POU_SYSTEM = 0x1; + public final static int POU_POOL = 0x2; + public final static int POU_PSET = 0x4; + public final static int POU_CPU = 0x8; + public final static int POX_NATIVE = get_POX_NATIVE(); + public final static int POX_TEXT = get_POX_TEXT(); + public final static int POC_INVAL = get_POC_INVAL(); + public final static int POC_UINT = get_POC_UINT(); + public final static int POC_INT = get_POC_INT(); + public final static int POC_DOUBLE = get_POC_DOUBLE(); + public final static int POC_BOOL = get_POC_BOOL(); + public final static int POC_STRING = get_POC_STRING(); + public final static int POV_NONE = get_POV_NONE(); + public final static int POV_LOOSE = get_POV_LOOSE(); + public final static int POV_STRICT = get_POV_STRICT(); + public final static int POV_RUNTIME = get_POV_RUNTIME(); + public final static int POF_INVALID = get_POF_INVALID(); + public final static int POF_VALID = get_POF_VALID(); + public final static int POF_DESTROY = get_POF_DESTROY(); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PoolsException.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PoolsException.java new file mode 100644 index 0000000000..fa49e3952d --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PoolsException.java @@ -0,0 +1,677 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.pools; + +/** + * The <code>PoolsException</code> class represents a pools error. It + * is used to report any errors in native code. See + * <code>errno(3C)</code> for information on the system (POE_SYSTEM) + * error codes. + */ +public class PoolsException extends Exception { + /** + * EPERM. + */ + public static final int EPERM = 1; + + /** + * ENOENT. + */ + public static final int ENOENT = 2; + + /** + * ESRCH. + */ + public static final int ESRCH = 3; + + /** + * EINTR. + */ + public static final int EINTR = 4; + + /** + * EIO. + */ + public static final int EIO = 5; + + /** + * ENXIO. + */ + public static final int ENXIO = 6; + + /** + * E2BIG. + */ + public static final int E2BIG = 7; + + /** + * ENOEXEC. + */ + public static final int ENOEXEC = 8; + + /** + * EBADF. + */ + public static final int EBADF = 9; + + /** + * ECHILD. + */ + public static final int ECHILD = 10; + + /** + * EAGAIN. + */ + public static final int EAGAIN = 11; + + /** + * ENOMEM. + */ + public static final int ENOMEM = 12; + + /** + * EACCES. + */ + public static final int EACCES = 13; + + /** + * EFAULT. + */ + public static final int EFAULT = 14; + + /** + * ENOTBLK. + */ + public static final int ENOTBLK = 15; + + /** + * EBUSY. + */ + public static final int EBUSY = 16; + + /** + * EEXIST. + */ + public static final int EEXIST = 17; + + /** + * EXDEV. + */ + public static final int EXDEV = 18; + + /** + * ENODEV. + */ + public static final int ENODEV = 19; + + /** + * ENOTDIR. + */ + public static final int ENOTDIR = 20; + + /** + * EISDIR. + */ + public static final int EISDIR = 21; + + /** + * EINVAL. + */ + public static final int EINVAL = 22; + + /** + * ENFILE. + */ + public static final int ENFILE = 23; + + /** + * EMFILE. + */ + public static final int EMFILE = 24; + + /** + * ENOTTY. + */ + public static final int ENOTTY = 25; + + /** + * ETXTBSY. + */ + public static final int ETXTBSY = 26; + + /** + * EFBIG. + */ + public static final int EFBIG = 27; + + /** + * ENOSPC. + */ + public static final int ENOSPC = 28; + + /** + * ESPIPE. + */ + public static final int ESPIPE = 29; + + /** + * EROFS. + */ + public static final int EROFS = 30; + + /** + * EMLINK. + */ + public static final int EMLINK = 31; + + /** + * EPIPE. + */ + public static final int EPIPE = 32; + + /** + * EDOM. + */ + public static final int EDOM = 33; + + /** + * ERANGE. + */ + public static final int ERANGE = 34; + + /** + * ENOMSG. + */ + public static final int ENOMSG = 35; + + /** + * EIDRM. + */ + public static final int EIDRM = 36; + + /** + * ECHRNG. + */ + public static final int ECHRNG = 37; + + /** + * EL2NSYNC. + */ + public static final int EL2NSYNC = 38; + + /** + * EL3HLT. + */ + public static final int EL3HLT = 39; + + /** + * EL3RST. + */ + public static final int EL3RST = 40; + + /** + * ELNRNG. + */ + public static final int ELNRNG = 41; + + /** + * EUNATCH. + */ + public static final int EUNATCH = 42; + + /** + * ENOCSI. + */ + public static final int ENOCSI = 43; + + /** + * EL2HLT. + */ + public static final int EL2HLT = 44; + + /** + * EDEADLK. + */ + public static final int EDEADLK = 45; + + /** + * ENOLCK. + */ + public static final int ENOLCK = 46; + + /** + * ECANCELED. + */ + public static final int ECANCELED = 47; + + /** + * ENOTSUP. + */ + public static final int ENOTSUP = 48; + + /** + * EDQUOT. + */ + public static final int EDQUOT = 49; + + /** + * EBADE. + */ + public static final int EBADE = 50; + + /** + * EBADR. + */ + public static final int EBADR = 51; + + /** + * EXFULL. + */ + public static final int EXFULL = 52; + + /** + * ENOANO. + */ + public static final int ENOANO = 53; + + /** + * EBADRQC. + */ + public static final int EBADRQC = 54; + + /** + * EBADSLT. + */ + public static final int EBADSLT = 55; + + /** + * EDEADLOCK. + */ + public static final int EDEADLOCK = 56; + + /** + * EBFONT. + */ + public static final int EBFONT = 57; + + /** + * EOWNERDEAD. + */ + public static final int EOWNERDEAD = 58; + + /** + * ENOTRECOVERABLE. + */ + public static final int ENOTRECOVERABLE = 59; + + /** + * ENOSTR. + */ + public static final int ENOSTR = 60; + + /** + * ENODATA. + */ + public static final int ENODATA = 61; + + /** + * ETIME. + */ + public static final int ETIME = 62; + + /** + * ENOSR. + */ + public static final int ENOSR = 63; + + /** + * ENONET. + */ + public static final int ENONET = 64; + + /** + * ENOPKG. + */ + public static final int ENOPKG = 65; + + /** + * EREMOTE. + */ + public static final int EREMOTE = 66; + + /** + * ENOLINK. + */ + public static final int ENOLINK = 67; + + /** + * EADV. + */ + public static final int EADV = 68; + + /** + * ESRMNT. + */ + public static final int ESRMNT = 69; + + /** + * ECOMM. + */ + public static final int ECOMM = 70; + + /** + * EPROTO. + */ + public static final int EPROTO = 71; + + /** + * ELOCKUNMAPPED. + */ + public static final int ELOCKUNMAPPED = 72; + + /** + * ENOTACTIVE. + */ + public static final int ENOTACTIVE = 73; + + /** + * EMULTIHOP. + */ + public static final int EMULTIHOP = 74; + + /** + * EBADMSG. + */ + public static final int EBADMSG = 77; + + /** + * ENAMETOOLONG. + */ + public static final int ENAMETOOLONG = 78; + + /** + * EOVERFLOW. + */ + public static final int EOVERFLOW = 79; + + /** + * ENOTUNIQ. + */ + public static final int ENOTUNIQ = 80; + + /** + * EBADFD. + */ + public static final int EBADFD = 81; + + /** + * EREMCHG. + */ + public static final int EREMCHG = 82; + + /** + * ELIBACC. + */ + public static final int ELIBACC = 83; + + /** + * ELIBBAD. + */ + public static final int ELIBBAD = 84; + + /** + * ELIBSCN. + */ + public static final int ELIBSCN = 85; + + /** + * ELIBMAX. + */ + public static final int ELIBMAX = 86; + + /** + * ELIBEXEC. + */ + public static final int ELIBEXEC = 87; + + /** + * EILSEQ. + */ + public static final int EILSEQ = 88; + + /** + * ENOSYS. + */ + public static final int ENOSYS = 89; + + /** + * ELOOP. + */ + public static final int ELOOP = 90; + + /** + * ERESTART. + */ + public static final int ERESTART = 91; + + /** + * ESTRPIPE. + */ + public static final int ESTRPIPE = 92; + + /** + * ENOTEMPTY. + */ + public static final int ENOTEMPTY = 93; + + /** + * EUSERS. + */ + public static final int EUSERS = 94; + + /** + * ENOTSOCK. + */ + public static final int ENOTSOCK = 95; + + /** + * EDESTADDRREQ. + */ + public static final int EDESTADDRREQ = 96; + + /** + * EMSGSIZE. + */ + public static final int EMSGSIZE = 97; + + /** + * EPROTOTYPE. + */ + public static final int EPROTOTYPE = 98; + + /** + * ENOPROTOOPT. + */ + public static final int ENOPROTOOPT = 99; + + /** + * EPROTONOSUPPORT. + */ + public static final int EPROTONOSUPPORT = 120; + + /** + * ESOCKTNOSUPPORT. + */ + public static final int ESOCKTNOSUPPORT = 121; + + /** + * EOPNOTSUPP. + */ + public static final int EOPNOTSUPP = 122; + + /** + * EPFNOSUPPORT. + */ + public static final int EPFNOSUPPORT = 123; + + /** + * EAFNOSUPPORT. + */ + public static final int EAFNOSUPPORT = 124; + + /** + * EADDRINUSE. + */ + public static final int EADDRINUSE = 125; + + /** + * EADDRNOTAVAIL. + */ + public static final int EADDRNOTAVAIL = 126; + + /** + * ENETDOWN. + */ + public static final int ENETDOWN = 127; + + /** + * ENETUNREACH. + */ + public static final int ENETUNREACH = 128; + + /** + * ENETRESET. + */ + public static final int ENETRESET = 129; + + /** + * ECONNABORTED. + */ + public static final int ECONNABORTED = 130; + + /** + * ECONNRESET. + */ + public static final int ECONNRESET = 131; + + /** + * ENOBUFS. + */ + public static final int ENOBUFS = 132; + + /** + * EISCONN. + */ + public static final int EISCONN = 133; + + /** + * ENOTCONN. + */ + public static final int ENOTCONN = 134; + + /** + * ESHUTDOWN. + */ + public static final int ESHUTDOWN = 143; + + /** + * ETOOMANYREFS. + */ + public static final int ETOOMANYREFS = 144; + + /** + * ETIMEDOUT. + */ + public static final int ETIMEDOUT = 145; + + /** + * ECONNREFUSED. + */ + public static final int ECONNREFUSED = 146; + + /** + * EHOSTDOWN. + */ + public static final int EHOSTDOWN = 147; + + /** + * EHOSTUNREACH. + */ + public static final int EHOSTUNREACH = 148; + + /** + * EALREADY. + */ + public static final int EALREADY = 149; + + /** + * EINPROGRESS. + */ + public static final int EINPROGRESS = 150; + + /** + * ESTALE. + */ + public static final int ESTALE = 151; + + private final int errorCode = PoolInternal.pool_error(); + + /** + * Constructor. + */ + public PoolsException() + { + super(description(PoolInternal.pool_error())); + } + + private static String description(int errorCode) + { + StringBuffer sb = new StringBuffer(PoolInternal.pool_strerror( + errorCode)); + if (errorCode == PoolInternal.POE_SYSTEM) + sb.append(": " + PoolInternal.pool_strerror_sys()); + return (sb.toString()); + } + + /** + * Returns the native pool error code. + * + * @return the native pool error code. + */ + public int getCode() + { + return (errorCode); + } + + /** + * Returns <code>errno</code>, if the pool error is + * <code>POE_SYSTEM</code>. + */ + public native int getErrno(); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Property.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Property.java new file mode 100644 index 0000000000..cf03d5835e --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Property.java @@ -0,0 +1,88 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +/** + * The <code>Property</code> interface specifies the contract between + * a pools configuration element and it's properties. This interface + * must be implemented by all pools configuration elements to ensure that + * properties can be manipulated. + */ + +public interface Property { + /** + * Get a property with the supplied name. + * + * @param name The name of the property to be retrieved. + * @throws PoolsExecption If there is an error accessing the property. + */ + public boolean getBoolProperty(String name) throws PoolsException; + + /** + * Get a property with the supplied name. + * + * @param name The name of the property to be retrieved. + * @throws PoolsExecption If there is an error accessing the property. + */ + public double getDoubleProperty(String name) throws PoolsException; + + /** + * Get a property with the supplied name. + * + * @param name The name of the property to be retrieved. + * @throws PoolsExecption If there is an error accessing the property. + */ + public long getLongProperty(String name) throws PoolsException; + + /** + * Get a property with the supplied name. + * + * @param name The name of the property to be retrieved. + * @throws PoolsExecption If there is an error accessing the property. + */ + public String getStringProperty(String name) throws PoolsException; + + /** + * Put the supplied value as a property with the supplied name. + * + * @param name The name of the property to be updated. + * @param value The value of the property to be updated. + * @throws PoolsExecption If there is an error accessing the property. + */ + public void putProperty(String name, Value value) throws PoolsException; + + /** + * Remove the property with the supplied name. + * + * @param name The name of the property to be removed. + * @throws PoolsExecption If there is an error removing the property. + */ + public void rmProperty(String name) throws PoolsException; +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PropertyWalk.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PropertyWalk.java new file mode 100644 index 0000000000..82f29845e0 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/PropertyWalk.java @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +import java.util.List; +import java.util.ArrayList; + +/** + * The <code>PropertyWalk</code> interface specifies the contract + * between a pools configuration element and clients which are + * interested in enumerating the properties of the element. + */ + +public interface PropertyWalk { + /** + * Walk all properties of the invoking object, calling the + * + * @param elem The element to whom the property belongs. + * @param val The value representing the current element. + * @param user User supplied data, provided when the walk is invoked. + * @throws PoolsExecption If there is an error walking the property. + * @return 0 to continue the walk, anything else to terminate it. + */ + public int walk(Element elem, Value val, Object user) + throws PoolsException; +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Resource.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Resource.java new file mode 100644 index 0000000000..babe05c015 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Resource.java @@ -0,0 +1,251 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.pools; + +import java.util.List; +import java.util.ArrayList; + +/** + * The <code>Resource</code> class represents a resource. + */ +public class Resource extends Element +{ + /** + * The type of the resource. + */ + private final String type; + /** + * The system id of the resource. + */ + private final String name; + /** + * The key of the resource. + */ + private final String key; + + /** + * Constructor + * @param conf The configuration to which this pool belongs. + * @param resource The pointer to the native resource which + * this object wraps. + * @throws PoolsException If accessing the proxy fails. + */ + Resource(Configuration conf, long resource) throws PoolsException + { + _conf = conf; + Value val = getProperty("type", resource); + type = val.getString(); + val.close(); + val = getProperty(type + ".name", resource); + name = val.getString(); + val.close(); + key = type + "." + name; + } + + /** + * Returns a pointer to the native resouce represented by this resource + * object. + * + * @throws PoolsException If the pool cannot be located. + * @return a pointer to the native resource represented by this + * resource object. + */ + long getResource() throws PoolsException + { + return (_conf.checkResource(type, name)); + } + + /** + * Transfer the requested quantity of resource from the donor to this + * resource. + * + * @param donor A donating resource. + * @param qty Amount of resource to be donated. + * @throws PoolsException If there is an error whilst donating the + * resource. + */ + public void transfer(Resource donor, long qty) throws PoolsException + { + if (PoolInternal.pool_resource_transfer(_conf.getConf(), + donor.getResource(), getResource(), qty) != + PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Transfer the specified resource components from the donor to this + * resource. + * + * @param donor A donating resource. + * @param components A list of resource components to be donated. + * @throws PoolsException If there is an error whilst donating the + * resource components. + */ + public void transfer(Resource donor, List components) + throws PoolsException + { + if (PoolInternal.pool_resource_xtransfer(_conf.getConf(), + donor.getResource(), getResource(), components) != + PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Get a list of components which match the supplied selection + * criteria in values. Only components which are controlled by + * this resource are searched. + * + * @param values A list of values to be used to qualify the search. + * @throws PoolsExecption If there is an error executing the query. + * @return a list of components which match the supplied criteria + */ + public List getComponents(List values) throws PoolsException + { + List components; + + if ((components = PoolInternal.pool_query_resource_components( + _conf.getConf(), getResource(), values)) == null) { + if (PoolInternal.pool_error() == 0 || + PoolInternal.pool_error() == + PoolInternal.POE_INVALID_SEARCH) + return new ArrayList(); + else + throw new PoolsException(); + } + ArrayList aList = new ArrayList(components.size()); + for (int i = 0; i < components.size(); i++) + aList.add(new Component(_conf, + ((Long)components.get(i)).longValue())); + return (aList); + } + + /** + * Returns a descriptive string which describes the resource. + * + * @param deep Whether the information should contain information about + * all contained elements. + * @throws PoolsException If the resource cannot be located. + * @return a descriptive string which describes the resource. + */ + public String getInformation(int deep) throws PoolsException + { + return (PoolInternal.pool_resource_info(_conf.getConf(), + getResource(), deep)); + } + + /** + * Returns a string representation of this resource. + * + * @return a string representation of this resource. + */ + public String toString() + { + StringBuffer buf = new StringBuffer(); + + buf.append(type); + buf.append(" "); + buf.append(name); + return (buf.toString()); + } + + /** + * Indicates whether some other Resource is "equal to this one. + * @param o the reference object with which to compare. + * @return <code>true</code> if this object is the same as the + * o argument; <code>false</code> otherwise. + * @see #hashCode() + */ + public boolean equals(Object o) + { + if (o == this) + return (true); + if (!(o instanceof Resource)) + return (false); + Resource other = (Resource) o; + if (type.compareTo(other.getType()) != 0 || + name.compareTo(other.getName()) != 0) + return (false); + return (true); + } + + /** + * Returns a hash code value for the object. This method is + * supported for the benefit of hashtables such as those provided by + * <code>java.util.Hashtable</code>. + * + * @return a hash code value for this object. + * @see #equals(java.lang.Object) + * @see java.util.Hashtable + */ + public int hashCode() + { + return (type.hashCode() + name.hashCode()); + } + + /** + * Return the pointer to this resource as an element. + * + * @return The pointer to the native resource which this object wraps. + * @throws PoolsExecption If there is an error converting the native + * resource pointer to a native elem pointer. + */ + protected long getElem() throws PoolsException + { + long elem; + + if ((elem = PoolInternal.pool_resource_to_elem(_conf.getConf(), + getResource())) == 0) + throw new PoolsException(); + return (elem); + } + + /** + * Return the type of the resource + */ + String getType() + { + return (type); + } + + /** + * Return the name of the resource. + */ + String getName() + { + return (name); + } + + /** + * Return the key of the resource. + */ + String getKey() + { + return (key); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/UnsignedInt64.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/UnsignedInt64.java new file mode 100644 index 0000000000..bcf367854f --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/UnsignedInt64.java @@ -0,0 +1,114 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.pools; + +import java.math.BigInteger; + +public class UnsignedInt64 extends BigInteger { + /** + * The minimum value is 0. + */ + public final static BigInteger MIN_VALUE = new BigInteger("0"); + + /** + * The maximum value is 18446744073709551615. + */ + public final static BigInteger MAX_VALUE = new BigInteger( + "18446744073709551615"); + + /** + * Constructs a UnsignedInt64 with the same value as the given + * string, interpreted in base 10. + * + * @throws NumberFormatException if the given value is outside + * the representable range. + */ + public UnsignedInt64(String string) throws NumberFormatException + { + super(string); + validate(this); + } + + /** + * Constructs a UnsignedInt64 with the same value as the given + * string, interpreted in the given base. + * + * @throws NumberFormatException if the given value is outside + * the representable range. + */ + public UnsignedInt64(String string, int radix) + throws NumberFormatException + { + super(string, radix); + validate(this); + } + + /** + * Constructs a UnsignedInt64 with the same value as the given + * byte array, interpreted as a two's-complement number in + * big-endian byte order (the most significant byte has the + * lowest index). + * + * @throws NumberFormatException if the given value is outside + * the representable range. + */ + public UnsignedInt64(byte[] bytes) throws NumberFormatException + { + super(bytes); + validate(this); + } + + /** + * Constructs an UnsignedInt64 with the same value as the given + * BigInteger. + * + * @throws NumberFormatException if the given value is outside + * the representable range. + */ + public UnsignedInt64(BigInteger value) throws NumberFormatException + { + super(value.toByteArray()); + validate(this); + } + + /** + * Check that the supplied parameter is a valid value for an + * UnsignedInt64. + * + * @param v A BigInteger to be checked if it's value is legal + * as an UnsignedInt64. + * @throws NumberFormatException if the given value is outside + * the representable range. + */ + private void validate(BigInteger v) + { + if (v.compareTo(MIN_VALUE) < 0 || v.compareTo(MAX_VALUE) > 0) + throw(new NumberFormatException()); + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Value.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Value.java new file mode 100644 index 0000000000..938cdd9446 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/Value.java @@ -0,0 +1,380 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + *ident "%Z%%M% %I% %E% SMI" + * + */ + +package com.sun.solaris.service.pools; + +/** + * The <code>Value</code> class represents a pools value. + */ +public class Value { + + private long _this; + + /** + * Constructor. Only for use from native code. + * @param pointer A pointer to a C value. + */ + private Value(long pointer) + { + _this = pointer; + } + + /** + * Constructor + * @param name The name of the value. + * @throws PoolsException If there is an error whilst + * allocating the value. + */ + public Value(String name) throws PoolsException + { + if ((_this = PoolInternal.pool_value_alloc()) == 0) + throw new PoolsException(); + setName(name); + } + + /** + * Constructor + * @param name The name of the value. + * @param value The value of the value. + * @throws PoolsException If there is an error whilst + * allocating the value. + */ + public Value(String name, long value) throws PoolsException + { + this(name); + setValue(value); + } + + /** + * Constructor + * @param name The name of the value. + * @param value The value of the value. + * @param s Indicates if the value is signed or not. + * @throws PoolsException If there is an error whilst + * allocating the value. + */ + public Value(String name, long value, boolean s) throws PoolsException + { + this(name); + setValue(value, s); + } + + /** + * Constructor + * @param name The name of the value. + * @param value The value of the value. + * @throws PoolsException If there is an error whilst + * allocating the value. + */ + public Value(String name, String value) throws PoolsException + { + this(name); + setValue(value); + } + + /** + * Constructor + * @param name The name of the value. + * @param value The value of the value. + * @throws PoolsException If there is an error whilst + * allocating the value. + */ + public Value(String name, boolean value) throws PoolsException + { + this(name); + setValue(value); + } + + /** + * Constructor + * @param name The name of the value. + * @param value The value of the value. + * @throws PoolsException If there is an error whilst + * allocating the value. + */ + public Value(String name, double value) throws PoolsException + { + this(name); + setValue(value); + } + + /** + * Explicitly reclaim the memory allocated for this value by + * the C proxy. + */ + public void close() + { + if (_this != 0) { + PoolInternal.pool_value_free(_this); + _this = 0; + } + } + + /** + * Reclaim the memory allocated for this value by the C + * proxy. + * + * @throws Throwable If freeing this configuration fails. + */ + protected void finalize() throws Throwable + { + try + { + close(); + } + finally + { + super.finalize(); + } + } + + /** + * Name this value. + * + * @param name The name to set for this value. + */ + public void setName(String name) + { + PoolInternal.pool_value_set_name(_this, name); + } + + /** + * Set this value to take the supplied signed long value. + * + * @param value The value to which this value should be set. + */ + public void setValue(long value) + { + PoolInternal.pool_value_set_int64(_this, value); + } + + /** + * Set this value to take the supplied long value. + * + * @param value The value to which this value should be set. + * @param s Is the value signed or unsigned. + */ + public void setValue(long value, boolean s) + { + if (s) + setValue(value); + PoolInternal.pool_value_set_uint64(_this, value); + } + + /** + * Set this value to take the supplied string value. + * + * @param value The value to which this value should be set. + * @throws PoolsExecption If the setting of the value fails. + */ + public void setValue(String value) throws PoolsException + { + if (PoolInternal.pool_value_set_string(_this, value) != + PoolInternal.PO_SUCCESS) + throw new PoolsException(); + } + + /** + * Set this value to take the supplied boolean value. + * + * @param value The value to which this value should be set. + */ + public void setValue(boolean value) + { + if (value == true) + PoolInternal.pool_value_set_bool(_this, (short)1); + else + PoolInternal.pool_value_set_bool(_this, (short)0); + } + + /** + * Set this value to take the supplied double value. + * + * @param value The value to which this value should be set. + */ + public void setValue(double value) + { + PoolInternal.pool_value_set_double(_this, value); + } + + /** + * Returns the name of the value. + * + * @return the name of the value. + */ + public String getName() + { + return (PoolInternal.pool_value_get_name(_this)); + } + + /** + * Returns the pointer to the native value represented by this + * object. + * + * @return the pointer to the native value represented by this + * object. + */ + public long getValue() + { + return (_this); + } + + /** + * Returns the type of this object. + * + * @return the type of this object. + */ + public int getType() + { + return (PoolInternal.pool_value_get_type(_this)); + } + + /** + * Returns a string representation of this value. + * + * @return a string representation of this value. + */ + public String toString() + { + int type = PoolInternal.pool_value_get_type(_this); + + try { + if (type == PoolInternal.POC_INT || + type == PoolInternal.POC_UINT) + return (String.valueOf(getLong())); + if (type == PoolInternal.POC_STRING) + return getString(); + if (type == PoolInternal.POC_BOOL) + return (String.valueOf(getBool())); + if (type == PoolInternal.POC_DOUBLE) + return (String.valueOf(getDouble())); + } + catch (PoolsException pe) { + return pe.toString(); + } + return ""; /* Stop the compiler complaining */ + } + + /** + * Returns the value as a UnsignedInt64. + * + * @return the value as a UnsignedInt64. + * @throws PoolsException if the value is not an + * UnsignedInt64. + */ + public final UnsignedInt64 getUnsignedInt64() throws PoolsException + { + return (getUnsignedInt64Value(_this)); + } + + /** + * Returns the value as a long. + * + * @return the value as a long. + * @throws PoolsException if the value is not a long. + */ + public final long getLong() throws PoolsException + { + return (getLongValue(_this)); + } + + /** + * Returns the value as a String. + * + * @return the value as a String. + * @throws PoolsException if the value is not a String. + */ + public final String getString() throws PoolsException + { + return (getStringValue(_this)); + } + + /** + * Returns the value as a boolean. + * + * @return the value as a boolean. + * @throws PoolsException if the value is not a boolean. + */ + public final boolean getBool() throws PoolsException + { + return (getBoolValue(_this)); + } + + /** + * Returns the value as a double. + * + * @return the value as a double. + * @throws PoolsException if the value is not a double. + */ + public final double getDouble() throws PoolsException + { + return (getDoubleValue(_this)); + } + + /** + * Returns the value as a UnsignedInt64. + * + * @param pointer the native value to be accessed. + * @return the value as a UnsignedInt64. + */ + private final static native UnsignedInt64 getUnsignedInt64Value( + long pointer); + + /** + * Returns the value as a long. + * + * @param pointer the native value to be accessed. + * @return the value as a long. + */ + private final static native long getLongValue(long pointer); + + /** + * Returns the value as a String. + * + * @param pointer the native value to be accessed. + * @return the value as a String. + */ + private final static native String getStringValue(long pointer); + + /** + * Returns the value as a boolean. + * + * @param pointer the native value to be accessed. + * @return the value as a boolean. + */ + private final static native boolean getBoolValue(long pointer); + + /** + * Returns the value as a double. + * + * @param pointer the native value to be accessed. + * @return the value as a double. + */ + private final static native double getDoubleValue(long pointer); +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/package.html new file mode 100644 index 0000000000..78951272b4 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/pools/package.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +Provides classes for manipulating Solaris Resource Pools. + + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2000/136/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, please see: +<ul> + <li><a href="http://taxman.eng/projects/administrative-support-processor-sets/">Resource Pools Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/Makefile b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/Makefile new file mode 100644 index 0000000000..6515004cd9 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/Makefile @@ -0,0 +1,48 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/com/sun/solaris/service/logging/Makefile + +include $(SRC)/cmd/Makefile.cmd + +CLASSPATH = $(SRC)/cmd/pools/poold +JAVAFLAGS += -source 1.4 + +SOURCE = RecurringEventTimer.java \ + SimpleRecurringEventTimer.java + +all install: $(SOURCE:.java=.class) + +# Since more than one class file can be generated from a java source +# file, any failure causes all class files to be removed. + +.FAILED: clean + +clean: + $(RM) *class + +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/RecurringEventTimer.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/RecurringEventTimer.java new file mode 100644 index 0000000000..4bfb7650d6 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/RecurringEventTimer.java @@ -0,0 +1,38 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.timer; + +/** + * An interface for for a timer for handling a recurring event at a + * uniform period. + */ +public interface RecurringEventTimer +{ + public void waitUntilNextFiring() throws InterruptedException; +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/SimpleRecurringEventTimer.java b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/SimpleRecurringEventTimer.java new file mode 100644 index 0000000000..558b6acf28 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/SimpleRecurringEventTimer.java @@ -0,0 +1,80 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * ident "%Z%%M% %I% %E% SMI" + */ + +package com.sun.solaris.service.timer; + +/** + * A recurring event timer. Like all Java time consumers, which rely on + * wall time, adjustments to the time of day will adversely affect the + * accuracy of the period. + */ +public class SimpleRecurringEventTimer implements RecurringEventTimer +{ + /** + * Next time the event is to occur. + */ + private long nextFiring; + + /** + * Period between recurrences of the event, in milliseconds. + */ + private long period; + + /** + * Multiplier to convert seconds to milliseconds. + */ + public static final int SEC = 1000; + + /** + * Establishes a timer which will fire every 'period' + * milliseconds starting from now. + */ + public SimpleRecurringEventTimer(long period) + { + this.period = period; + nextFiring = System.currentTimeMillis() + period; + } + + /** + * Cause the current thread to wait until at least the time of + * the next event, as near as possible, unless interrupted. + * + * @throws InterruptedException if the thread is interrupted + * while waiting for the next firing. Subsequent calls to this + * method will wait for the same firing. + */ + public void waitUntilNextFiring() throws InterruptedException + { + long delta; + + while ((delta = nextFiring - System.currentTimeMillis()) > 0) + Thread.sleep(delta); + + nextFiring += period; + } +} diff --git a/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/package.html b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/package.html new file mode 100644 index 0000000000..59a925dc49 --- /dev/null +++ b/usr/src/cmd/pools/poold/com/sun/solaris/service/timer/package.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> +<!-- + Copyright 2005 Sun Microsystems, Inc. All rights reserved. + Use is subject to license terms. + + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License, Version 1.0 only + (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 + ident "%Z%%M% %I% %E% SMI" +--> +</head> +<body bgcolor="white"> + +Provides classes implementing timers suitable for use by a daemon. + +<h2>Package Specification</h2> + +<ul> + <li><a href="http://sac.eng.sun.com/arc/PSARC/2002/287/">PSARC Case Directory</a> +</ul> + +<h2>Related Documentation</h2> + +For overviews, tutorials, examples, guides, and tool documentation, +please see: +<ul> + <li><a href="http://taxman.eng/projects/dynamic-resource-pools/">Dynamic Resource Pools Project Page</a> +</ul> + +<!-- Put @see and @since tags down here. --> + +</body> +</html> diff --git a/usr/src/cmd/pools/poold/libjkstat/Makefile b/usr/src/cmd/pools/poold/libjkstat/Makefile new file mode 100644 index 0000000000..0e23e77ff5 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/Makefile @@ -0,0 +1,63 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/Makefile +# + +include $(SRC)/lib/Makefile.lib + +SUBDIRS = spec .WAIT $(MACH) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +JNI_CLASSES = \ + com.sun.solaris.service.kstat.Kstat \ + com.sun.solaris.service.kstat.KstatCtl + +JNI_GENERATED_HEADERS = \ + jkstat.h + +CLEANFILES += $(JNI_GENERATED_HEADERS) + +all install lint: $(JNI_GENERATED_HEADERS) .WAIT $(SUBDIRS) + +clean clobber: $(SUBDIRS) + +$(JNI_GENERATED_HEADERS): $(SRC)/cmd/pools/poold/JPool.jar + $(JAVAH) -classpath $? -o $@ $(JNI_CLASSES) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ +include $(SRC)/Makefile.msg.targ diff --git a/usr/src/cmd/pools/poold/libjkstat/Makefile.com b/usr/src/cmd/pools/poold/libjkstat/Makefile.com new file mode 100644 index 0000000000..a8871f0bc3 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/Makefile.com @@ -0,0 +1,53 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/Makefile.com +# + +LIBRARY = libjkstat.a +VERS = .1 + +OBJECTS = jkstat.o + +include $(SRC)/lib/Makefile.lib + +INCS = -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +LIBS = $(DYNLIB) +LDLIBS += -lkstat +ROOTLIBDIR = $(ROOT)/usr/lib/pool +SRCDIR = $(SRC)/cmd/pools/poold/libjkstat + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64 $(INCS) + +all: $(LIBS) + +lint: lintcheck + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/cmd/pools/poold/libjkstat/i386/Makefile b/usr/src/cmd/pools/poold/libjkstat/i386/Makefile new file mode 100644 index 0000000000..0f84e63530 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/i386/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/i386/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/i386 + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjkstat/jkstat.c b/usr/src/cmd/pools/poold/libjkstat/jkstat.c new file mode 100644 index 0000000000..fb627ada48 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/jkstat.c @@ -0,0 +1,421 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stddef.h> +#include <kstat.h> + +#include "jkstat.h" + +/* + * Class descriptors + */ +#define DOUBLE_CLASS_DESC "java/lang/Double" +#define LONG_CLASS_DESC "java/lang/Long" +#define UI64_CLASS_DESC "com/sun/solaris/service/pools/UnsignedInt64" +#define HRTIME_CLASS_DESC "com/sun/solaris/service/pools/HRTime" +#define KSTAT_CLASS_DESC "com/sun/solaris/service/kstat/Kstat" +#define KSTATCTL_CLASS_DESC "com/sun/solaris/service/kstat/KstatCtl" +#define KSTAT_READ_EX_CLASS_DESC \ + "com/sun/solaris/service/kstat/KstatReadException" +#define KSTAT_TNS_EX_CLASS_DESC \ + "com/sun/solaris/service/kstat/KstatTypeNotSupportedException" +#define THROWABLE_CLASS_DESC "java/lang/Throwable" + +#define CLASS_FIELD_DESC(class_desc) "L" class_desc ";" + +/* + * Cached class, method, and field IDs. + */ +static jclass doubleclass; +static jclass hrtimeclass; +static jclass kstatclass; +static jclass kstatctlclass; +static jclass longclass; +static jclass ui64class; +static jfieldID kstat_kctl_fieldid; +static jfieldID kstat_ksp_fieldid; +static jfieldID kstatctl_kctl_fieldid; +static jmethodID doublecons_mid; +static jmethodID hrtimecons_mid; +static jmethodID kstatcons_mid; +static jmethodID longcons_mid; +static jmethodID ui64cons_mid; + +static jobject +makeUnsignedInt64(JNIEnv *env, uint64_t value) +{ + jobject valueObj; + jobject byteArray; + jbyte *bytes; + int i; + + if (!(byteArray = (*env)->NewByteArray(env, 9))) + return (NULL); /* OutOfMemoryError thrown */ + if (!(bytes = (*env)->GetByteArrayElements(env, byteArray, NULL))) + return (NULL); /* OutOfMemoryError thrown */ + + /* + * Interpret the uint64_t as a 9-byte big-endian signed quantity + * suitable for constructing an UnsignedInt64 or BigInteger. + */ + for (i = 8; i >= 1; i--) { + bytes[i] = value & 0xff; + value >>= 8; + } + bytes[0] = 0; + (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0); + + if (!(valueObj = (*env)->NewObject(env, ui64class, ui64cons_mid, + byteArray))) + return (NULL); /* exception thrown */ + + return (valueObj); +} + +/* + * Return a Long object with the given value. + */ +static jobject +makeLong(JNIEnv *env, jlong value) +{ + jobject valueObj; + + if (!(valueObj = (*env)->NewObject(env, longclass, longcons_mid, + value))) + return (NULL); /* exception thrown */ + + return (valueObj); +} + +/* + * Return a Double object with the given value. + */ +static jobject +makeDouble(JNIEnv *env, jdouble value) +{ + jobject valueObj; + + if (!(valueObj = (*env)->NewObject(env, doubleclass, doublecons_mid, + value))) + return (NULL); /* exception thrown */ + + return (valueObj); +} + +/* + * Returns the kctl_t * from kstat_open(3kstat). + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_kstat_KstatCtl_open(JNIEnv *env, jobject obj) +{ + return ((jlong)(uintptr_t)kstat_open()); +} + +/* + * Invokes kstat_close(3kstat). + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_kstat_KstatCtl_close(JNIEnv *env, jobject obj, + jlong kctl) +{ + if (kctl) + return (kstat_close((kstat_ctl_t *)kctl)); + else + return (0); +} + +/* + * Invoke kstat_read(3kstat) for the given Kstat object. + */ +JNIEXPORT void JNICALL Java_com_sun_solaris_service_kstat_Kstat_read( + JNIEnv *env, jobject obj) +{ + kstat_ctl_t *kctl = ((kstat_ctl_t *)(*env)->GetLongField(env, obj, + kstat_kctl_fieldid)); + kstat_t *ksp = ((kstat_t *)(*env)->GetLongField(env, obj, + kstat_ksp_fieldid)); + kid_t kid; + + if (!ksp || !kctl) + return; /* exception thronw */ + + kid = kstat_read((kstat_ctl_t *)kctl, (kstat_t *)ksp, NULL); + if (kid == -1) { + jclass e; + if (!(e = (*env)->FindClass(env, KSTAT_READ_EX_CLASS_DESC))) + return; /* exception thrown */ + + (*env)->Throw(env, (*env)->NewObject(env, e, + (*env)->GetStaticMethodID(env, e, "<init>", + "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); + } +} + +/* + * Return a Kstat object corresponding to the result of + * kstat_lookup(3kstat). + */ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_kstat_KstatCtl_lookup(JNIEnv *env, jobject obj, + jstring moduleObj, jint instance, jstring nameObj) +{ + const char *module = NULL; + const char *name = NULL; + kstat_ctl_t *kctl; + kstat_t *ksp; + jobject kstatObject = NULL; + + if (moduleObj == NULL || nameObj == NULL) + return (NULL); + + if (!(module = (*env)->GetStringUTFChars(env, moduleObj, NULL))) + goto done; /* exception thrown */ + if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) + goto done; /* exception thrown */ + + kctl = (kstat_ctl_t *)(*env)->GetLongField(env, obj, + kstatctl_kctl_fieldid); + ksp = kstat_lookup(kctl, (char *)module, instance, (char *)name); + if (ksp) + kstatObject = (*env)->NewObject(env, kstatclass, kstatcons_mid, + (jlong)(uintptr_t)kctl, (jlong)(uintptr_t)ksp); + +done: + if (name) + (*env)->ReleaseStringUTFChars(env, nameObj, name); + if (module) + (*env)->ReleaseStringUTFChars(env, moduleObj, module); + + return (kstatObject); +} + +/* + * Returns the named value -- the value of the named kstat, or field in + * a raw kstat, as applicable, and available. Returns <i>null</i> if no + * such named kstat or field is available. + * + * Throws KstatTypeNotSupportedException if the raw kstat is not + * understood. (Presently, none are.) + */ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_kstat_Kstat_getValue(JNIEnv *env, jobject obj, + jstring nameObj) +{ + kstat_t *ksp = ((kstat_t *)(*env)->GetLongField(env, obj, + kstat_ksp_fieldid)); + jobject valueObj = NULL; + kstat_named_t *ksnp; + const char *name; + jclass exceptionClass; + + if (!nameObj) + return (NULL); + + if (!(name = (*env)->GetStringUTFChars(env, nameObj, NULL))) + return (NULL); /* exception thrown */ + + if (!(exceptionClass = (*env)->FindClass(env, + KSTAT_TNS_EX_CLASS_DESC))) { + (*env)->ReleaseStringUTFChars(env, nameObj, name); + return (NULL); /* exception thrown */ + } + + switch (ksp->ks_type) { + case KSTAT_TYPE_NAMED: + ksnp = kstat_data_lookup(ksp, (char *)name); + if (ksnp == NULL) + break; + switch (ksnp->data_type) { + case KSTAT_DATA_CHAR: + valueObj = makeLong(env, ksnp->value.c[0]); + break; + case KSTAT_DATA_INT32: + valueObj = makeLong(env, ksnp->value.i32); + break; + case KSTAT_DATA_UINT32: + valueObj = makeLong(env, ksnp->value.ui32); + break; + case KSTAT_DATA_INT64: + valueObj = makeLong(env, ksnp->value.i64); + break; + case KSTAT_DATA_UINT64: + valueObj = makeUnsignedInt64(env, ksnp->value.ui64); + break; + case KSTAT_DATA_STRING: + valueObj = (*env)->NewStringUTF(env, + KSTAT_NAMED_STR_PTR(ksnp)); + break; + case KSTAT_DATA_FLOAT: + valueObj = makeDouble(env, ksnp->value.f); + break; + case KSTAT_DATA_DOUBLE: + valueObj = makeDouble(env, ksnp->value.d); + break; + default: + goto fail; + } + break; + default: + goto fail; + } + + (*env)->ReleaseStringUTFChars(env, nameObj, name); + return (valueObj); + +fail: + (*env)->ReleaseStringUTFChars(env, nameObj, name); + (*env)->Throw(env, (*env)->NewObject(env, exceptionClass, + (*env)->GetStaticMethodID(env, exceptionClass, "<init>", + "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); + + return (valueObj); +} + +/* + * Given a Kstat object, return, as an HRTime object, its kstat_t's + * field at the given offset. + */ +static jobject +ksobj_get_hrtime(JNIEnv *env, jobject obj, offset_t ksfieldoff) +{ + kstat_t *ksp = ((kstat_t *)(*env)->GetLongField(env, obj, + kstat_ksp_fieldid)); + + if (!ksp) + return (NULL); /* exception thrown */ + + return ((*env)->NewObject(env, hrtimeclass, hrtimecons_mid, + makeUnsignedInt64(env, *((hrtime_t *)ksp + ksfieldoff * + sizeof (hrtime_t))))); +} + +/* + * Given a Kstat object, return as an HRTime object its ks_snaptime + * field. + */ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_kstat_Kstat_getSnapTime(JNIEnv *env, jobject obj) +{ + return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_snaptime))); +} + +/* + * Given a Kstat object, return as an HRTime object its ks_crtime + * field. + */ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_kstat_Kstat_getCreationTime(JNIEnv *env, + jobject obj) +{ + return (ksobj_get_hrtime(env, obj, offsetof(kstat_t, ks_crtime))); +} + +/* + * Invoke kstat_chain_update(3kstat) for the kstat chain corresponding + * to the given KstatCtl object. + */ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate(JNIEnv *env, + jobject obj) +{ + kstat_ctl_t *kctl; + + kctl = (kstat_ctl_t *)(*env)->GetLongField(env, obj, + kstatctl_kctl_fieldid); + + (void) kstat_chain_update(kctl); +} + +/* + * Cache class, method, and field IDs. + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_kstat_KstatCtl_init(JNIEnv *env, jclass clazz) +{ + jclass doubleclass_lref; + jclass hrtimeclass_lref; + jclass kstatclass_lref; + jclass kstatctlclass_lref; + jclass longclass_lref; + jclass ui64class_lref; + + if (!(doubleclass_lref = (*env)->FindClass(env, DOUBLE_CLASS_DESC))) + return; /* exception thrown */ + if (!(doubleclass = (*env)->NewGlobalRef(env, doubleclass_lref))) + return; /* exception thrown */ + if (!(doublecons_mid = (*env)->GetMethodID(env, doubleclass, "<init>", + "(D)V"))) + return; /* exception thrown */ + + if (!(hrtimeclass_lref = (*env)->FindClass(env, HRTIME_CLASS_DESC))) + return; /* exception thrown */ + if (!(hrtimeclass = (*env)->NewGlobalRef(env, hrtimeclass_lref))) + return; /* exception thrown */ + if (!(hrtimecons_mid = (*env)->GetMethodID(env, hrtimeclass, "<init>", + "(" CLASS_FIELD_DESC(UI64_CLASS_DESC) ")V"))) + return; /* exception thrown */ + + if (!(kstatclass_lref = (*env)->FindClass(env, KSTAT_CLASS_DESC))) + return; /* exception thrown */ + if (!(kstatclass = (*env)->NewGlobalRef(env, kstatclass_lref))) + return; /* exception thrown */ + if (!(kstatcons_mid = (*env)->GetMethodID(env, kstatclass, "<init>", + "(JJ)V"))) + return; /* exception thrown */ + if (!(kstat_kctl_fieldid = (*env)->GetFieldID(env, kstatclass, "kctl", + "J"))) + return; /* exception thrown */ + if (!(kstat_ksp_fieldid = (*env)->GetFieldID(env, kstatclass, "ksp", + "J"))) + return; /* exception thrown */ + + if (!(kstatctlclass_lref = (*env)->FindClass(env, KSTATCTL_CLASS_DESC))) + return; /* exception thrown */ + if (!(kstatctlclass = (*env)->NewGlobalRef(env, kstatctlclass_lref))) + return; /* exception thrown */ + if (!(kstatctl_kctl_fieldid = (*env)->GetFieldID(env, kstatctlclass, + "kctl", "J"))) + return; /* exception thrown */ + + if (!(longclass_lref = (*env)->FindClass(env, LONG_CLASS_DESC))) + return; /* exception thrown */ + if (!(longclass = (*env)->NewGlobalRef(env, longclass_lref))) + return; /* exception thrown */ + if (!(longcons_mid = (*env)->GetMethodID(env, longclass, "<init>", + "(J)V"))) + return; /* exception thrown */ + + if (!(ui64class_lref = (*env)->FindClass(env, UI64_CLASS_DESC))) + return; /* exception thrown */ + if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref))) + return; /* exception thrown */ + ui64cons_mid = (*env)->GetMethodID(env, ui64class, "<init>", "([B)V"); +} diff --git a/usr/src/cmd/pools/poold/libjkstat/sparc/Makefile b/usr/src/cmd/pools/poold/libjkstat/sparc/Makefile new file mode 100644 index 0000000000..1350b66bcf --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/sparc/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/sparc/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/sparc + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/Makefile b/usr/src/cmd/pools/poold/libjkstat/spec/Makefile new file mode 100644 index 0000000000..24a6d4bf52 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/Makefile +# + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/Makefile.targ b/usr/src/cmd/pools/poold/libjkstat/spec/Makefile.targ new file mode 100644 index 0000000000..0d7392118f --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/Makefile.targ @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/Makefile.targ +# + +.KEEP_STATE: + +LIBRARY = libjkstat.a +VERS = .1 + +OBJECTS = jkstat.o diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/amd64/Makefile b/usr/src/cmd/pools/poold/libjkstat/spec/amd64/Makefile new file mode 100644 index 0000000000..1add7fe765 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/amd64/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/i386/Makefile b/usr/src/cmd/pools/poold/libjkstat/spec/i386/Makefile new file mode 100644 index 0000000000..4bd5775646 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/i386/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/jkstat.spec b/usr/src/cmd/pools/poold/libjkstat/spec/jkstat.spec new file mode 100644 index 0000000000..55571135de --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/jkstat.spec @@ -0,0 +1,101 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/jkstat.spec + +function Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate +include "../../jkstat.h" +declaration void \ + Java_com_sun_solaris_service_kstat_KstatCtl_chainUpdate \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_KstatCtl_close +include "../../jkstat.h" +declaration int \ + Java_com_sun_solaris_service_kstat_KstatCtl_close \ + (JNIEnv *env, jobject obj, jlong kctl) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_KstatCtl_init +include "../../jkstat.h" +declaration void \ + Java_com_sun_solaris_service_kstat_KstatCtl_init \ + (JNIEnv *env, jclass clazz) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_KstatCtl_lookup +include "../../jkstat.h" +declaration jobject \ + Java_com_sun_solaris_service_kstat_KstatCtl_lookup \ + (JNIEnv *env, jobject obj, jstring moduleObj, \ + jint instance, jstring nameObj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_KstatCtl_open +include "../../jkstat.h" +declaration jlong \ + Java_com_sun_solaris_service_kstat_KstatCtl_open \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_Kstat_getCreationTime +include "../../jkstat.h" +declaration jobject \ + Java_com_sun_solaris_service_kstat_Kstat_getCreationTime \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_Kstat_getSnapTime +include "../../jkstat.h" +declaration jobject \ + Java_com_sun_solaris_service_kstat_Kstat_getSnapTime \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_Kstat_getValue +include "../../jkstat.h" +declaration jobject \ + Java_com_sun_solaris_service_kstat_Kstat_getValue \ + (JNIEnv *env, jobject obj, jstring nameObj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_kstat_Kstat_read +include "../../jkstat.h" +declaration void \ + Java_com_sun_solaris_service_kstat_Kstat_read \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/sparc/Makefile b/usr/src/cmd/pools/poold/libjkstat/spec/sparc/Makefile new file mode 100644 index 0000000000..c755776ae9 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/sparc/Makefile @@ -0,0 +1,41 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/sparcv9/Makefile b/usr/src/cmd/pools/poold/libjkstat/spec/sparcv9/Makefile new file mode 100644 index 0000000000..304c1d6ef3 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/sparcv9/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec/sparcv9/Makefile + +DISABLE_APPTRACE= $(POUND_SIGN) +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 +include $(SRC)/lib/Makefile.spec + +$(DISABLE_APPTRACE)install: $(ROOTABILIB64) diff --git a/usr/src/cmd/pools/poold/libjkstat/spec/versions b/usr/src/cmd/pools/poold/libjkstat/spec/versions new file mode 100644 index 0000000000..9455f211e2 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjkstat/spec/versions @@ -0,0 +1,36 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjkstat/spec versions +# + +i386 { + SUNWprivate_1.1; +} + +sparc { + SUNWprivate_1.1; +} diff --git a/usr/src/cmd/pools/poold/libjlgrp/Makefile b/usr/src/cmd/pools/poold/libjlgrp/Makefile new file mode 100644 index 0000000000..a7d93d5174 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/Makefile @@ -0,0 +1,63 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/Makefile +# + +include $(SRC)/lib/Makefile.lib + +SUBDIRS = spec .WAIT $(MACH) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +JNI_CLASSES = \ + com.sun.solaris.service.locality.LocalityDomain \ + com.sun.solaris.service.locality.LocalityGroup + +JNI_GENERATED_HEADERS = \ + jlgrp.h + +CLEANFILES += $(JNI_GENERATED_HEADERS) + +all install lint: $(JNI_GENERATED_HEADERS) .WAIT $(SUBDIRS) + +clean clobber: $(SUBDIRS) + +$(JNI_GENERATED_HEADERS): $(SRC)/cmd/pools/poold/JPool.jar + $(JAVAH) -classpath $? -o $@ $(JNI_CLASSES) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ +include $(SRC)/Makefile.msg.targ diff --git a/usr/src/cmd/pools/poold/libjlgrp/Makefile.com b/usr/src/cmd/pools/poold/libjlgrp/Makefile.com new file mode 100644 index 0000000000..68ef5bf483 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/Makefile.com @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/Makefile.com +# + +LIBRARY = libjlgrp.a +VERS = .1 + +OBJECTS = jlgrp.o + +include $(SRC)/lib/Makefile.lib + +INCS = -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +MAPFILE = $(MAPDIR)/mapfile + +LIBS = $(DYNLIB) +LDLIBS += -llgrp -lc +ROOTLIBDIR = $(ROOT)/usr/lib/pool +SRCDIR = $(SRC)/cmd/pools/poold/libjlgrp + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64 $(INCS) + +all: $(LIBS) + +lint: lintcheck + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/cmd/pools/poold/libjlgrp/i386/Makefile b/usr/src/cmd/pools/poold/libjlgrp/i386/Makefile new file mode 100644 index 0000000000..76ad708f5c --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/i386/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/i386/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/i386 + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjlgrp/jlgrp.c b/usr/src/cmd/pools/poold/libjlgrp/jlgrp.c new file mode 100644 index 0000000000..8ec78b7cf6 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/jlgrp.c @@ -0,0 +1,250 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + + +#include <stdlib.h> +#include <sys/lgrp_user.h> + +#include "jlgrp.h" + +static lgrp_cookie_t getCookie(JNIEnv *, jclass, jobject); +static void throwException(JNIEnv *, const char *, const char *); + +/* + * Return the output of the getCookie() method executed on the + * supplied instance. + */ +lgrp_cookie_t +getCookie(JNIEnv *env, jclass clazz, jobject obj) +{ + jfieldID fid; + + fid = (*env)->GetFieldID(env, clazz, "cookie", "J"); + return ((lgrp_cookie_t)(*env)->GetLongField(env, obj, fid)); +} + +/* + * Throw an exception of the specified class with the specified message. + */ +void +throwException(JNIEnv *env, const char *class, const char *msg) +{ + jclass clazz; + + clazz = (*env)->FindClass(env, class); + + (*env)->ThrowNew(env, clazz, msg); +} + +/* + * Obtain an lgrp cookie for an lgrp snapshot which contains details + * about available resources that the operating system knows about. + * + * If the call fails, then throw an exception which indicates that the + * snapshot could not be obtained. + */ +/*ARGSUSED1*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_locality_LocalityDomain_jl_1init(JNIEnv *env, + jobject obj, jint view) +{ + lgrp_cookie_t cookie; + + if ((cookie = lgrp_init(view)) == LGRP_COOKIE_NONE) { + throwException(env, "java/lang/Exception", + "Could not obtain latency group cookie"); + } + + return ((jlong)cookie); +} + +/* + * Release the snapshot in use by this instance. It is assumed that + * the cookie is held in the "cookie" field of the invoking instance + */ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_locality_LocalityDomain_jl_1fini(JNIEnv *env, + jobject obj) +{ + jclass clazz; + + clazz = (*env)->GetObjectClass(env, obj); + return ((jint)lgrp_fini(getCookie(env, clazz, obj))); +} + +/* + * Create a new LocalityGroup object which acts as a proxy for the + * root LocalityGroup. + */ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_locality_LocalityDomain_jl_1root(JNIEnv *env, + jobject obj) +{ + jclass clazz; + jmethodID mid; + jlong root; + jobject lgrp; + + clazz = (*env)->GetObjectClass(env, obj); + + root = (jlong) lgrp_root(getCookie(env, clazz, obj)); + + clazz = (*env)->FindClass(env, "com/sun/solaris/service/locality/" + "LocalityGroup"); + mid = (*env)->GetMethodID(env, clazz, "<init>", "(Lcom/sun/solaris/" + "service/locality/LocalityDomain;JLcom/sun/solaris/service/" + "locality/LocalityGroup;)V"); + lgrp = (*env)->NewObject(env, clazz, mid, obj, root, NULL); + return (lgrp); +} + +/* + * Return a new array containing all of the child LocalityGroup ids + * for the supplied instance. + */ +JNIEXPORT jlongArray JNICALL +Java_com_sun_solaris_service_locality_LocalityGroup_jl_1children(JNIEnv *env, + jobject obj) +{ + jclass clazz; + jfieldID fid; + lgrp_cookie_t cookie; + jlong id; + jsize nchild0, nchild; + jlongArray children; + int i; + lgrp_id_t *native_child; + jlong *java_child; + jobject domain; + + clazz = (*env)->GetObjectClass(env, obj); + fid = (*env)->GetFieldID(env, clazz, "domain", + "Lcom/sun/solaris/service/locality/LocalityDomain;"); + domain = (*env)->GetObjectField(env, obj, fid); + + cookie = getCookie(env, (*env)->GetObjectClass(env, domain), domain); + fid = (*env)->GetFieldID(env, clazz, "id", "J"); + id = (*env)->GetLongField(env, obj, fid); +retry: + nchild0 = (jsize)lgrp_children(cookie, (lgrp_id_t)id, NULL, 0); + children = (*env)->NewLongArray(env, nchild0); + if ((native_child = calloc(nchild0, sizeof (lgrp_id_t))) == NULL) { + throwException(env, "java/lang/Exception", + "Could not allocate memory for native_child array"); + return (NULL); + } + nchild = lgrp_children(cookie, (lgrp_id_t)id, native_child, nchild0); + if (nchild != nchild0) { + free(native_child); + goto retry; + } + + if ((java_child = calloc(nchild, sizeof (jlong))) == NULL) { + throwException(env, "java/lang/Exception", + "Could not allocate memory for java_child array"); + free(native_child); + return (NULL); + } + + for (i = 0; i < nchild; i++) + java_child[i] = (jlong) native_child[i]; + (*env)->SetLongArrayRegion(env, children, 0, nchild, java_child); + free(native_child); + free(java_child); + return (children); +} + +/* + * Return a new array containing all of the cpus contained directly + * within the LocalityGroup identified by the supplied instance. + */ +JNIEXPORT jintArray JNICALL +Java_com_sun_solaris_service_locality_LocalityGroup_jl_1cpus(JNIEnv *env, + jobject obj) +{ + jclass clazz; + jfieldID fid; + lgrp_cookie_t cookie; + jlong id; + jsize ncpus0, ncpus; + jintArray cpus; + int i; + processorid_t *native_cpus; + jint *java_cpus; + jobject domain; + + clazz = (*env)->GetObjectClass(env, obj); + fid = (*env)->GetFieldID(env, clazz, "domain", + "Lcom/sun/solaris/service/locality/LocalityDomain;"); + domain = (*env)->GetObjectField(env, obj, fid); + + cookie = getCookie(env, (*env)->GetObjectClass(env, domain), domain); + + fid = (*env)->GetFieldID(env, clazz, "id", "J"); + id = (*env)->GetLongField(env, obj, fid); +retry: + ncpus0 = (jsize)lgrp_cpus((lgrp_cookie_t)cookie, (lgrp_id_t)id, + NULL, 0, LGRP_CONTENT_DIRECT); + cpus = (*env)->NewIntArray(env, ncpus0); + if ((native_cpus = calloc(ncpus0, sizeof (processorid_t))) == NULL) { + throwException(env, "java/lang/Exception", + "Could not allocate memory for native_cpus array"); + return (NULL); + } + ncpus = (jsize)lgrp_cpus((lgrp_cookie_t)cookie, (lgrp_id_t)id, + native_cpus, ncpus0, LGRP_CONTENT_DIRECT); + if (ncpus != ncpus0) { + free(native_cpus); + goto retry; + } + + if ((java_cpus = calloc(ncpus, sizeof (jint))) == NULL) { + free(native_cpus); + throwException(env, "java/lang/Exception", + "Could not allocate memory for java_cpus array"); + return (NULL); + } + + for (i = 0; i < ncpus; i++) + java_cpus[i] = (jint)native_cpus[i]; + (*env)->SetIntArrayRegion(env, cpus, 0, ncpus, java_cpus); + free(native_cpus); + free(java_cpus); + return (cpus); +} + +/* + * Return the latency between two supplied latency group IDs. + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_locality_LocalityGroup_jl_1latency(JNIEnv *env, + jobject obj, jlong from, jlong to) +{ + return ((jint) lgrp_latency((lgrp_id_t)from, (lgrp_id_t)to)); +} diff --git a/usr/src/cmd/pools/poold/libjlgrp/sparc/Makefile b/usr/src/cmd/pools/poold/libjlgrp/sparc/Makefile new file mode 100644 index 0000000000..8dbc2500a1 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/sparc/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/sparc/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/sparc + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/Makefile b/usr/src/cmd/pools/poold/libjlgrp/spec/Makefile new file mode 100644 index 0000000000..a5107dd9f9 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/Makefile +# + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/Makefile.targ b/usr/src/cmd/pools/poold/libjlgrp/spec/Makefile.targ new file mode 100644 index 0000000000..48cdd9a230 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/Makefile.targ @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/Makefile.targ +# + +.KEEP_STATE: + +LIBRARY = libjlgrp.a +VERS = .1 + +OBJECTS = jlgrp.o diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/amd64/Makefile b/usr/src/cmd/pools/poold/libjlgrp/spec/amd64/Makefile new file mode 100644 index 0000000000..e827ac53f6 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/amd64/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/i386/Makefile b/usr/src/cmd/pools/poold/libjlgrp/spec/i386/Makefile new file mode 100644 index 0000000000..f9d884b09f --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/i386/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/jlgrp.spec b/usr/src/cmd/pools/poold/libjlgrp/spec/jlgrp.spec new file mode 100644 index 0000000000..81bc8189a6 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/jlgrp.spec @@ -0,0 +1,76 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/jlgrp.spec + +function Java_com_sun_solaris_service_locality_LocalityDomain_jl_1fini +include "../../jlgrp.h" +declaration jint \ + Java_com_sun_solaris_service_locality_LocalityDomain_jl_1fini \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_locality_LocalityDomain_jl_1init +include "../../jlgrp.h" +declaration jlong \ + Java_com_sun_solaris_service_locality_LocalityDomain_jl_1init \ + (JNIEnv *env, jobject obj, jint view) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_locality_LocalityDomain_jl_1root +include "../../jlgrp.h" +declaration jobject \ + Java_com_sun_solaris_service_locality_LocalityDomain_jl_1root \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_locality_LocalityGroup_jl_1children +include "../../jlgrp.h" +declaration jlongArray \ + Java_com_sun_solaris_service_locality_LocalityGroup_jl_1children \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_locality_LocalityGroup_jl_1cpus +include "../../jlgrp.h" +declaration jintArray \ + Java_com_sun_solaris_service_locality_LocalityGroup_jl_1cpus \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_locality_LocalityGroup_jl_1latency +include "../../jlgrp.h" +declaration jint \ + Java_com_sun_solaris_service_locality_LocalityGroup_jl_1latency \ + (JNIEnv *env, jobject obj, jlong from, jlong to) +version SUNWprivate_1.1 +end + diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/sparc/Makefile b/usr/src/cmd/pools/poold/libjlgrp/spec/sparc/Makefile new file mode 100644 index 0000000000..ae86fd7d13 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/sparc/Makefile @@ -0,0 +1,41 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/sparcv9/Makefile b/usr/src/cmd/pools/poold/libjlgrp/spec/sparcv9/Makefile new file mode 100644 index 0000000000..da5f498611 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/sparcv9/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec/sparcv9/Makefile + +DISABLE_APPTRACE= $(POUND_SIGN) +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 +include $(SRC)/lib/Makefile.spec + +$(DISABLE_APPTRACE)install: $(ROOTABILIB64) diff --git a/usr/src/cmd/pools/poold/libjlgrp/spec/versions b/usr/src/cmd/pools/poold/libjlgrp/spec/versions new file mode 100644 index 0000000000..2d7d033084 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjlgrp/spec/versions @@ -0,0 +1,36 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjlgrp/spec versions +# + +i386 { + SUNWprivate_1.1; +} + +sparc { + SUNWprivate_1.1; +} diff --git a/usr/src/cmd/pools/poold/libjpool/Makefile b/usr/src/cmd/pools/poold/libjpool/Makefile new file mode 100644 index 0000000000..198a9ef241 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/Makefile @@ -0,0 +1,65 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/Makefile +# + +include $(SRC)/lib/Makefile.lib + +SUBDIRS = spec .WAIT $(MACH) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +JNI_CLASSES = \ + com.sun.solaris.service.pools.PoolInternal \ + com.sun.solaris.service.pools.Element \ + com.sun.solaris.service.pools.Value \ + com.sun.solaris.service.pools.HRTime + +JNI_GENERATED_HEADERS = \ + jpool.h + +CLEANFILES += $(JNI_GENERATED_HEADERS) + +all install lint: $(JNI_GENERATED_HEADERS) .WAIT $(SUBDIRS) + +clean clobber: $(SUBDIRS) + +$(JNI_GENERATED_HEADERS): $(SRC)/cmd/pools/poold/JPool.jar + $(JAVAH) -classpath $? -o $@ $(JNI_CLASSES) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ +include $(SRC)/Makefile.msg.targ diff --git a/usr/src/cmd/pools/poold/libjpool/Makefile.com b/usr/src/cmd/pools/poold/libjpool/Makefile.com new file mode 100644 index 0000000000..3de6d694a5 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/Makefile.com @@ -0,0 +1,56 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/Makefile.com +# + +LIBRARY = libjpool.a +VERS = .1 + +OBJECTS = jpool.o + +include $(SRC)/lib/Makefile.lib + +INCS = -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +MAPFILE = $(MAPDIR)/mapfile + +LIBS = $(DYNLIB) +DYNFLAGS += -M $(MAPFILE) +LDLIBS += -lpool -lc +ROOTLIBDIR = $(ROOT)/usr/lib/pool +SRCDIR = $(SRC)/cmd/pools/poold/libjpool + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64 $(INCS) + +all: $(LIBS) + +lint: lintcheck + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/cmd/pools/poold/libjpool/i386/Makefile b/usr/src/cmd/pools/poold/libjpool/i386/Makefile new file mode 100644 index 0000000000..5540c23533 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/i386/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/i386/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/i386 + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjpool/jpool.c b/usr/src/cmd/pools/poold/libjpool/jpool.c new file mode 100644 index 0000000000..c2144a9297 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/jpool.c @@ -0,0 +1,1759 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <errno.h> +#include <jni.h> +#include <pool.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/time.h> + +#include "jpool.h" + +struct pool_callback { + jobject pc_user; + jobject pc_handler; + jobject pc_elem; + JNIEnv *pc_env; +}; + +static void throwException(JNIEnv *, const char *, const char *); +static void throw_pe(JNIEnv *); +static jobject makeUnsignedInt64(JNIEnv *, uint64_t); +static int pool_property_walker(pool_conf_t *, pool_elem_t *p, const char *, + pool_value_t *, void *); +static jobject copyArray(JNIEnv *, void **); + +/* + * Cached class, method, and field IDs. + */ +static jclass ui64class; +static jmethodID ui64cons_mid; + +/* + * Throw an exception of the specified class with the specified message. + */ +void +throwException(JNIEnv *env, const char *class, const char *msg) +{ + jclass clazz; + + clazz = (*env)->FindClass(env, class); + + (*env)->ThrowNew(env, clazz, msg); +} + +/* + * Throw a PoolsException. + */ +void +throw_pe(JNIEnv *jenv) +{ + jclass clazz; + jmethodID mid; + jthrowable throwObj; + + clazz = (*jenv)->FindClass(jenv, + "com/sun/solaris/service/pools/PoolsException"); + mid = (*jenv)->GetMethodID(jenv, clazz, "<init>", "()V"); + throwObj = (*jenv)->NewObject(jenv, clazz, mid); + (*jenv)->Throw(jenv, throwObj); +} + +/* + * Return an instance of an UnsignedInt64 class which encapsulates the + * supplied value. + */ +jobject +makeUnsignedInt64(JNIEnv *env, uint64_t value) +{ + jobject valueObj; + jobject byteArray; + jbyte *bytes; + int i; + + if (!(byteArray = (*env)->NewByteArray(env, 9))) + return (NULL); /* OutOfMemoryError thrown */ + if (!(bytes = (*env)->GetByteArrayElements(env, byteArray, NULL))) + return (NULL); /* OutOfMemoryError thrown */ + + /* + * Interpret the uint64_t as a 9-byte big-endian signed quantity + * suitable for constructing an UnsignedInt64 or BigInteger. + */ + for (i = 8; i >= 1; i--) { + bytes[i] = value & 0xff; + value >>= 8; + } + bytes[0] = 0; + (*env)->ReleaseByteArrayElements(env, byteArray, bytes, 0); + + if (!(valueObj = (*env)->NewObject(env, ui64class, ui64cons_mid, + byteArray))) + return (NULL); /* exception thrown */ + + return (valueObj); +} + +/* + * Create an array list and then copy the native array into it + */ +jobject +copyArray(JNIEnv *jenv, void **nativeArray) +{ + int i; + jobject jresult = NULL; + + if (nativeArray != NULL) { + jclass ALclazz; + jmethodID ALinit, ALadd; + jclass Lclazz; + jmethodID Linit; + + ALclazz = (*jenv)->FindClass(jenv, + "java/util/ArrayList"); + ALinit = (*jenv)->GetMethodID(jenv, + ALclazz, "<init>", "()V"); + ALadd = (*jenv)->GetMethodID(jenv, + ALclazz, "add", "(Ljava/lang/Object;)Z"); + jresult = (*jenv)->NewObject(jenv, ALclazz, ALinit); + Lclazz = (*jenv)->FindClass(jenv, "java/lang/Long"); + Linit = (*jenv)->GetMethodID(jenv, + Lclazz, "<init>", "(J)V"); + for (i = 0; nativeArray[i] != NULL; i++) { + jobject L; + /* Build longs and add them */ + L = (*jenv)->NewObject(jenv, + Lclazz, Linit, (jlong)(uintptr_t)nativeArray[i]); + (*jenv)->CallBooleanMethod(jenv, + jresult, ALadd, L); + } + free(nativeArray); + } + return (jresult); +} + +/* + * pool_version(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1version(JNIEnv *jenv, + jclass jcls, jlong jver) { + return ((jlong)pool_version((uint_t)jver)); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POX_1NATIVE(JNIEnv *jenv, + jclass jcls) { + return ((jint)POX_NATIVE); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POX_1TEXT(JNIEnv *jenv, + jclass jcls) { + return ((jint)POX_TEXT); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1INVAL(JNIEnv *jenv, + jclass jcls) { + return ((jint)POC_INVAL); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1UINT(JNIEnv *jenv, + jclass jcls) { + return ((jint)POC_UINT); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1INT(JNIEnv *jenv, + jclass jcls) { + return ((jint)POC_INT); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1DOUBLE(JNIEnv *jenv, + jclass jcls) { + return ((jint)POC_DOUBLE); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1BOOL(JNIEnv *jenv, + jclass jcls) { + return ((jint)POC_BOOL); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1STRING(JNIEnv *jenv, + jclass jcls) { + return ((jint)POC_STRING); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1NONE(JNIEnv *jenv, + jclass jcls) { + return ((jint)POV_NONE); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1LOOSE(JNIEnv *jenv, + jclass jcls) { + return ((jint)POV_LOOSE); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1STRICT(JNIEnv *jenv, + jclass jcls) { + return ((jint)POV_STRICT); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1RUNTIME(JNIEnv *jenv, + jclass jcls) { + return ((jint)POV_RUNTIME); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1INVALID(JNIEnv *jenv, + jclass jcls) { + return ((jint)POF_INVALID); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1VALID(JNIEnv *jenv, + jclass jcls) { + return ((jint)POF_VALID); +} + +/* + * native constant accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1DESTROY(JNIEnv *jenv, + jclass jcls) { + return ((jint)POF_DESTROY); +} + +/* + * pool_error(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1error(JNIEnv *jenv, + jclass jcls) { + return ((jint)pool_error()); +} + +/* + * pool_strerror(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1strerror(JNIEnv *jenv, + jclass jcls, jint jperr) { + jstring jresult = NULL; + char *result; + + result = (char *)pool_strerror((int)jperr); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + return (jresult); +} + +/* + * strerror(3c) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1strerror_1sys(JNIEnv * + jenv, jclass jcls) { + jstring jresult = NULL; + char *result; + + result = (char *)strerror(errno); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + return (jresult); +} + +/* + * errno(3c) accessor + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolsException_getErrno(JNIEnv *jenv, + jclass jcls) { + return ((jint)errno); +} + +/* + * pool_resource_type_list(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1type_1list( + JNIEnv *jenv, jclass jcls, jlong jreslist, jlong jnumres) { + char **reslist = (char **)jreslist; + uint_t *numres = (uint_t *)jnumres; + + return ((jint)pool_resource_type_list((char const **)reslist, numres)); +} + +/* + * pool_get_status(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1status(JNIEnv *jenv, + jclass jcls, jlong jstatep) { + return ((jint)pool_get_status((int *)jstatep)); +} + +/* + * pool_set_status(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1set_1status(JNIEnv *jenv, + jclass jcls, jint jstate) { + return ((jint)pool_set_status((int)jstate)); +} + +/* + * pool_conf_alloc(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1alloc(JNIEnv *jenv, + jclass jcls) { + return ((jlong)(uintptr_t)pool_conf_alloc()); +} + +/* + * pool_conf_free(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1free(JNIEnv *jenv, + jclass jcls, jlong jconf) { + pool_conf_free((pool_conf_t *)jconf); +} + +/* + * pool_conf_status(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1status(JNIEnv *jenv, + jclass jcls, jlong jconf) { + return ((jint)pool_conf_status((pool_conf_t *)jconf)); +} + +/* + * pool_conf_close(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1close(JNIEnv *jenv, + jclass jcls, jlong jconf) { + return ((jint)pool_conf_close((pool_conf_t *)jconf)); +} + +/* + * pool_conf_remove(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1remove(JNIEnv *jenv, + jclass jcls, jlong jconf) { + return ((jint)pool_conf_remove((pool_conf_t *)jconf)); +} + +/* + * pool_conf_open(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1open(JNIEnv *jenv, + jclass jcls, jlong jconf, jstring jlocation, jint jflags) { + const char *location; + int result; + + location = (jlocation) ? (*jenv)->GetStringUTFChars(jenv, + jlocation, 0) : NULL; + result = (int)pool_conf_open((pool_conf_t *)jconf, location, + (int)jflags); + + if (location) + (*jenv)->ReleaseStringUTFChars(jenv, jlocation, location); + return ((jint)result); +} + +/* + * pool_conf_rollback(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1rollback( + JNIEnv *jenv, jclass jcls, jlong jconf) { + return ((jint)pool_conf_rollback((pool_conf_t *)jconf)); +} + +/* + * pool_conf_commit(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1commit(JNIEnv *jenv, + jclass jcls, jlong jconf, jint jactive) { + return ((jint)pool_conf_commit((pool_conf_t *)jconf, (int)jactive)); +} + +/* + * pool_conf_export(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1export(JNIEnv *jenv, + jclass jcls, jlong jconf, jstring jlocation, jint jformat) { + const char *location; + int result; + + location = (jlocation) ? (*jenv)->GetStringUTFChars(jenv, + jlocation, 0) : NULL; + result = (int)pool_conf_export((pool_conf_t *)jconf, + location, (pool_export_format_t)jformat); + + if (location) + (*jenv)->ReleaseStringUTFChars(jenv, jlocation, location); + return ((jint)result); +} + +/* + * pool_conf_validate(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1validate( + JNIEnv *jenv, jclass jcls, jlong jconf, jint jlevel) { + return ((jint)pool_conf_validate((pool_conf_t *)jconf, + (pool_valid_level_t)jlevel)); +} + +/* + * pool_conf_update(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1update(JNIEnv *jenv, + jclass jcls, jlong jconf) { + int changed; + int result; + + result = pool_conf_update((pool_conf_t *)jconf, &changed); + + if (result != PO_SUCCESS) { + throw_pe(jenv); + } + + return ((jint)changed); +} + +/* + * pool_get_pool(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1pool(JNIEnv *jenv, + jclass jcls, jlong jconf, jstring jname) { + const char *name; + pool_t *result; + + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : + NULL; + result = (pool_t *)pool_get_pool((pool_conf_t *)jconf, name); + + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jlong)(uintptr_t)result); +} + +/* + * pool_query_pools(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1pools(JNIEnv *jenv, + jclass jcls, jlong jconf, jobject jprops) { + pool_value_t **props; + pool_t **result; + jclass Lclazz; + jmethodID Lsize; + jint size; + uint_t nelem; + int i; + + + /* + * Initialize the target parameter for case when input is null + */ + props = NULL; + if (jprops != NULL) { + Lclazz = (*jenv)->GetObjectClass(jenv, jprops); + Lsize = (*jenv)->GetMethodID(jenv, Lclazz, "size", "()I"); + size = (*jenv)->CallIntMethod(jenv, jprops, Lsize); + + if (size != 0) { + jmethodID Lget; + + Lget = (*jenv)->GetMethodID(jenv, Lclazz, "get", + "(I)Ljava/lang/Object;"); + /* + * Allocate space for the props array + */ + + if ((props = calloc(size + 1, sizeof (pool_value_t *))) + == NULL) { + throwException(jenv, "java/lang/Exception", + "Could not allocate props array"); + return (NULL); + } + /* + * Copy in the array + */ + for (i = 0; i < size; i++) { + jobject aVal; + jclass Vclazz; + jfieldID Vthis; + jlong this; + + aVal = (*jenv)->CallObjectMethod(jenv, jprops, + Lget, (jint) i); + Vclazz = (*jenv)->GetObjectClass(jenv, aVal); + Vthis = (*jenv)->GetFieldID(jenv, Vclazz, + "_this", "J"); + this = (*jenv)->GetLongField(jenv, aVal, Vthis); + props[i] = (pool_value_t *)this; + } + } + } + result = pool_query_pools((pool_conf_t *)jconf, &nelem, + props); + free(props); + return (copyArray(jenv, (void **)result)); +} + +/* + * pool_get_resource(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1resource( + JNIEnv *jenv, jclass jcls, jlong jconf, jstring jtype, jstring jname) { + const char *type; + const char *name; + pool_resource_t *result; + + type = (jtype) ? (*jenv)->GetStringUTFChars(jenv, jtype, 0) : + NULL; + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : + NULL; + result = pool_get_resource((pool_conf_t *)jconf, type, name); + + if (type) + (*jenv)->ReleaseStringUTFChars(jenv, jtype, type); + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jlong)(uintptr_t)result); +} + +/* + * pool_query_resources(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1resources( + JNIEnv *jenv, jclass jcls, jlong jconf, jobject jprops) { + pool_value_t **props; + pool_resource_t **result; + jclass Lclazz; + jmethodID Lsize; + jint size; + uint_t nelem; + int i; + + /* + * Initialize the target parameter for case when input is null + */ + props = NULL; + if (jprops != NULL) { + Lclazz = (*jenv)->GetObjectClass(jenv, jprops); + Lsize = (*jenv)->GetMethodID(jenv, Lclazz, "size", "()I"); + size = (*jenv)->CallIntMethod(jenv, jprops, Lsize); + + if (size != 0) { + jmethodID Lget; + + Lget = (*jenv)->GetMethodID(jenv, Lclazz, "get", + "(I)Ljava/lang/Object;"); + /* + * Allocate space for the props array + */ + if ((props = calloc(size + 1, sizeof (pool_value_t *))) + == NULL) { + throwException(jenv, "java/lang/Exception", + "Could not allocate props array"); + return (NULL); + } + /* + * Copy in the array + */ + for (i = 0; i < size; i++) { + jobject aVal; + jclass Vclazz; + jfieldID Vthis; + jlong this; + + + aVal = (*jenv)->CallObjectMethod(jenv, jprops, + Lget, (jint) i); + Vclazz = (*jenv)->GetObjectClass(jenv, aVal); + Vthis = (*jenv)->GetFieldID(jenv, Vclazz, + "_this", "J"); + this = (*jenv)->GetLongField(jenv, aVal, Vthis); + props[i] = (pool_value_t *)this; + } + } + } + result = pool_query_resources((pool_conf_t *)jconf, &nelem, + props); + free(props); + return (copyArray(jenv, (void *)result)); +} + +/* + * pool_query_components(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1components( + JNIEnv *jenv, jclass jcls, jlong jconf, jobject jprops) { + pool_value_t **props; + pool_component_t **result; + jclass Lclazz; + jmethodID Lsize; + jint size; + uint_t nelem; + int i; + + /* + * Initialize the target parameter for case when input is null + */ + props = NULL; + if (jprops != NULL) { + Lclazz = (*jenv)->GetObjectClass(jenv, jprops); + Lsize = (*jenv)->GetMethodID(jenv, Lclazz, "size", "()I"); + size = (*jenv)->CallIntMethod(jenv, jprops, Lsize); + + if (size != 0) { + jmethodID Lget; + + Lget = (*jenv)->GetMethodID(jenv, Lclazz, "get", + "(I)Ljava/lang/Object;"); + /* + * Allocate space for the props array + */ + + if ((props = calloc(size + 1, sizeof (pool_value_t *))) + == NULL) { + throwException(jenv, "java/lang/Exception", + "Could not allocate props array"); + return (NULL); + } + /* + * Copy in the array + */ + for (i = 0; i < size; i++) { + jobject aVal; + jclass Vclazz; + jfieldID Vthis; + jlong this; + + aVal = (*jenv)->CallObjectMethod(jenv, jprops, + Lget, (jint) i); + Vclazz = (*jenv)->GetObjectClass(jenv, aVal); + Vthis = (*jenv)->GetFieldID(jenv, Vclazz, + "_this", "J"); + this = (*jenv)->GetLongField(jenv, aVal, Vthis); + props[i] = (pool_value_t *)this; + } + } + } + result = pool_query_components((pool_conf_t *)jconf, &nelem, + props); + free(props); + return (copyArray(jenv, (void **)result)); +} + +/* + * pool_conf_location(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1location( + JNIEnv *jenv, jclass jcls, jlong jconf) { + jstring jresult = NULL; + const char *result; + + result = pool_conf_location((pool_conf_t *)jconf); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + return (jresult); +} + +/* + * pool_conf_info(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1info(JNIEnv *jenv, + jclass jcls, jlong jconf, jint jflags) { + jstring jresult = NULL; + const char *result; + + result = pool_conf_info((pool_conf_t *)jconf, (int)jflags); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + free((void *)result); + return (jresult); +} + +/* + * pool_resource_create(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1create( + JNIEnv *jenv, jclass jcls, jlong jconf, jstring jtype, jstring jname) { + const char *type; + const char *name; + pool_resource_t *result; + + type = (jtype) ? (*jenv)->GetStringUTFChars(jenv, jtype, 0) : + NULL; + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : + NULL; + result = pool_resource_create((pool_conf_t *)jconf, type, name); + + if (type) + (*jenv)->ReleaseStringUTFChars(jenv, jtype, type); + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jlong)(uintptr_t)result); +} + +/* + * pool_resource_destroy(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1destroy( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource) { + return ((jint)pool_resource_destroy((pool_conf_t *)jconf, + (pool_resource_t *)jresource)); +} + +/* + * pool_resource_transfer(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1transfer( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jsource, jlong jtarget, + jlong jsize) { + return (pool_resource_transfer((pool_conf_t *)jconf, + (pool_resource_t *)jsource, (pool_resource_t *)jtarget, + (uint64_t)jsize)); +} + +/* + * pool_resource_xtransfer(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1xtransfer( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jsource, jlong jtarget, + jobject jcomponents) { + pool_component_t **components; + int result; + jclass Lclazz; + jmethodID Lsize; + jint size; + + /* + * Initialize the target parameter for case when input is null + */ + components = NULL; + if (jcomponents != NULL) { + Lclazz = (*jenv)->GetObjectClass(jenv, jcomponents); + Lsize = (*jenv)->GetMethodID(jenv, Lclazz, "size", "()I"); + size = (*jenv)->CallIntMethod(jenv, jcomponents, Lsize); + + if (size != 0) { + jmethodID Lget; + int i; + + Lget = (*jenv)->GetMethodID(jenv, + Lclazz, "get", "(I)Ljava/lang/Object;"); + /* Allocate space for the components array */ + + if ((components = calloc(size + 1, + sizeof (pool_component_t *))) == NULL) { + throwException(jenv, "java/lang/Exception", + "Could not allocate component array"); + return (NULL); + } + /* + * Copy in the array + */ + for (i = 0; i < size; i++) { + jobject aVal; + jclass Vclazz; + jlong this; + jmethodID Vthis; + + aVal = (*jenv)->CallObjectMethod(jenv, + jcomponents, Lget, (jint) i); + Vclazz = (*jenv)->GetObjectClass(jenv, + aVal); + Vthis = (*jenv)->GetMethodID(jenv, + Vclazz, "getComponent", "()J"); + this = (*jenv)->CallLongMethod(jenv, + aVal, Vthis); + components[i] = (pool_component_t *)this; + } + } + } + result = (int)pool_resource_xtransfer((pool_conf_t *)jconf, + (pool_resource_t *)jsource, (pool_resource_t *)jtarget, + components); + free(components); + + return ((jint)result); +} + +/* + * pool_query_resource_components(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1resource_\ +1components(JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource, + jobject jprops) { + pool_value_t **props; + pool_component_t **result; + jclass Lclazz; + jmethodID Lsize; + uint_t nelem; + jint size; + + /* + * Initialize the target parameter for case when input is null + */ + props = NULL; + if (jprops != NULL) { + Lclazz = (*jenv)->GetObjectClass(jenv, jprops); + Lsize = (*jenv)->GetMethodID(jenv, Lclazz, "size", "()I"); + size = (*jenv)->CallIntMethod(jenv, jprops, Lsize); + + if (size != 0) { + jmethodID Lget; + int i; + + Lget = (*jenv)->GetMethodID(jenv, Lclazz, "get", + "(I)Ljava/lang/Object;"); + /* + * Allocate space for the props array + */ + if ((props = calloc(size + 1, sizeof (pool_value_t *))) + == NULL) { + throwException(jenv, "java/lang/Exception", + "Could not allocate props array"); + return (NULL); + } + /* + * Copy in the array + */ + for (i = 0; i < size; i++) { + jobject aVal; + jclass Vclazz; + jfieldID Vthis; + jlong this; + + aVal = (*jenv)->CallObjectMethod(jenv, jprops, + Lget, (jint) i); + Vclazz = (*jenv)->GetObjectClass(jenv, aVal); + Vthis = (*jenv)->GetFieldID(jenv, Vclazz, + "_this", "J"); + this = (*jenv)->GetLongField(jenv, aVal, Vthis); + props[i] = (pool_value_t *)this; + } + } + } + result = pool_query_resource_components((pool_conf_t *)jconf, + (pool_resource_t *)jresource, &nelem, props); + free(props); + return (copyArray(jenv, (void **)result)); +} + +/* + * pool_resource_info(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1info( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource, jint jflags) { + jstring jresult = NULL; + const char *result; + + result = (char *)pool_resource_info((pool_conf_t *)jconf, + (pool_resource_t *)jresource, (int)jflags); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + free((void *)result); + return (jresult); +} + +/* + * pool_create(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1create(JNIEnv *jenv, + jclass jcls, jlong jconf, jstring jname) { + const char *name; + pool_t *result; + + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : + NULL; + result = pool_create((pool_conf_t *)jconf, name); + + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jlong)(uintptr_t)result); +} + +/* + * pool_destroy(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1destroy(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jpool) { + return ((jint)pool_destroy((pool_conf_t *)jconf, (pool_t *)jpool)); +} + +/* + * pool_associate(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1associate(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jpool, jlong jresource) { + return ((jint)pool_associate((pool_conf_t *)jconf, (pool_t *)jpool, + (pool_resource_t *)jresource)); +} + +/* + * pool_dissociate(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1dissociate(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jpool, jlong jresource) { + return ((jint)pool_dissociate((pool_conf_t *)jconf, (pool_t *)jpool, + (pool_resource_t *)jresource)); +} + +/* + * pool_info(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1info(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jpool, jint jflags) { + jstring jresult = NULL; + const char *result; + + result = pool_info((pool_conf_t *)jconf, + (pool_t *)jpool, (int)jflags); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + free((void *)result); + return (jresult); +} + +/* + * pool_query_pool_resources(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1pool_1resources( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, jobject jprops) { + pool_value_t **props; + pool_resource_t **result; + jclass Lclazz; + jmethodID Lsize; + uint_t nelem; + jint size; + + /* + * Initialize the target parameter for case when input is null + */ + props = NULL; + if (jprops != NULL) { + Lclazz = (*jenv)->GetObjectClass(jenv, jprops); + Lsize = (*jenv)->GetMethodID(jenv, Lclazz, "size", "()I"); + size = (*jenv)->CallIntMethod(jenv, jprops, Lsize); + + if (size != 0) { + jmethodID Lget; + int i; + + Lget = (*jenv)->GetMethodID(jenv, + Lclazz, "get", "(I)Ljava/lang/Object;"); + /* + * Allocate space for the props array + */ + + if ((props = calloc(size + 1, sizeof (pool_value_t *))) + == NULL) { + throwException(jenv, "java/lang/Exception", + "Could not allocate props array"); + return (NULL); + } + /* + * Copy in the array + */ + for (i = 0; i < size; i++) { + jobject aVal; + jclass Vclazz; + jfieldID Vthis; + jlong this; + + aVal = (*jenv)->CallObjectMethod(jenv, jprops, + Lget, (jint) i); + Vclazz = (*jenv)->GetObjectClass(jenv, aVal); + Vthis = (*jenv)->GetFieldID(jenv, Vclazz, + "_this", "J"); + this = (*jenv)->GetLongField(jenv, aVal, Vthis); + props[i] = (pool_value_t *)this; + } + } + } + result = pool_query_pool_resources((pool_conf_t *)jconf, + (pool_t *)jpool, &nelem, props); + free(props); + return (copyArray(jenv, (void **)result)); +} + +/* + * pool_get_owning_resource(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1owning_1resource( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jcomponent) { + return ((jlong)(uintptr_t)pool_get_owning_resource((pool_conf_t *)jconf, + (pool_component_t *)jcomponent)); +} + +/* + * pool_component_info(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1component_1info( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jcomponent, jint jflags) { + jstring jresult = NULL; + const char *result; + + result = pool_component_info((pool_conf_t *)jconf, + (pool_component_t *)jcomponent, (int)jflags); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + free((void *)result); + return (jresult); +} + +/* + * pool_get_property(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1property( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, jstring jname, + jlong jproperty) { + const char *name; + int result; + + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : + NULL; + result = pool_get_property((pool_conf_t *)jconf, + (pool_elem_t *)jelem, name, (pool_value_t *)jproperty); + + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jint)result); +} + +/* + * pool_put_property(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1put_1property( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, jstring jname, + jlong jvalue) { + const char *name; + int result; + + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : NULL; + result = (int)pool_put_property((pool_conf_t *)jconf, + (pool_elem_t *)jelem, name, (pool_value_t *)jvalue); + + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jint)result); +} + +/* + * pool_rm_property(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1rm_1property(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jelem, jstring jname) { + const char *name; + int result; + + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : NULL; + result = pool_rm_property((pool_conf_t *)jconf, (pool_elem_t *)jelem, + name); + + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jint)result); +} + +/* + * pool_walk_properties(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1properties( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, jlong jarg, + jlong jcallback) { + int result; + + result = (int)pool_walk_properties((pool_conf_t *)jconf, + (pool_elem_t *)jelem, (void *)jarg, + (int (*)(pool_conf_t *, pool_elem_t *, char const *, + pool_value_t *, void *))jcallback); + + return ((jint)result); +} + +/* + * pool_conf_to_elem(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1to_1elem( + JNIEnv *jenv, jclass jcls, jlong jconf) { + return ((jlong)(uintptr_t)pool_conf_to_elem((pool_conf_t *)jconf)); +} + +/* + * pool_to_elem(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1to_1elem(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jpool) { + return ((jlong)(uintptr_t)pool_to_elem((pool_conf_t *)jconf, + (pool_t *)jpool)); +} + +/* + * pool_resource_to_elem(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1to_1elem( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource) { + return ((jlong)(uintptr_t)pool_resource_to_elem((pool_conf_t *)jconf, + (pool_resource_t *)jresource)); +} + +/* + * pool_component_to_elem(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1component_1to_1elem( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jcomponent) { + return ((jlong)(uintptr_t)pool_component_to_elem((pool_conf_t *)jconf, + (pool_component_t *)jcomponent)); +} + +/* + * pool_value_get_type(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1get_1type( + JNIEnv *jenv, jclass jcls, jlong jvalue) { + return ((jint)pool_value_get_type((pool_value_t *)jvalue)); +} + +/* + * pool_value_set_uint64(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1uint64( + JNIEnv *jenv, jclass jcls, jlong jvalue, jlong jui64) { + pool_value_set_uint64((pool_value_t *)jvalue, (uint64_t)jui64); +} + +/* + * pool_value_set_int64(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1int64( + JNIEnv *jenv, jclass jcls, jlong jvalue, jlong ji64) { + pool_value_set_int64((pool_value_t *)jvalue, (int64_t)ji64); +} + +/* + * pool_value_set_double(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1double( + JNIEnv *jenv, jclass jcls, jlong jvalue, jdouble jd) { + pool_value_set_double((pool_value_t *)jvalue, (double)jd); +} + +/* + * pool_value_set_bool(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1bool( + JNIEnv *jenv, jclass jcls, jlong jvalue, jshort jb) { + pool_value_set_bool((pool_value_t *)jvalue, (uchar_t)jb); +} + +/* + * pool_value_set_string(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1string( + JNIEnv * jenv, jclass jcls, jlong jvalue, jstring jstr) { + const char *str; + int result; + + str = (jstr) ? (*jenv)->GetStringUTFChars(jenv, jstr, 0) : NULL; + result = pool_value_set_string((pool_value_t *)jvalue, str); + + if (str) + (*jenv)->ReleaseStringUTFChars(jenv, jstr, str); + return ((jint)result); +} + +/* + * pool_value_get_name(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1get_1name( + JNIEnv *jenv, jclass jcls, jlong jvalue) { + jstring jresult = NULL; + const char *result; + + result = pool_value_get_name((pool_value_t *)jvalue); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + return (jresult); +} + +/* + * pool_value_set_name(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1name( + JNIEnv *jenv, jclass jcls, jlong jvalue, jstring jname) { + const char *name; + int result; + + name = (jname) ? (*jenv)->GetStringUTFChars(jenv, jname, 0) : NULL; + result = pool_value_set_name((pool_value_t *)jvalue, name); + + if (name) + (*jenv)->ReleaseStringUTFChars(jenv, jname, name); + return ((jint)result); +} + +/* + * pool_value_alloc(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1alloc(JNIEnv *jenv, + jclass jcls) { + return ((jlong)(uintptr_t)pool_value_alloc()); +} + +/* + * pool_value_free(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1free(JNIEnv *jenv, + jclass jcls, jlong jvalue) { + pool_value_free((pool_value_t *)jvalue); +} + +/* + * pool_static_location(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1static_1location( + JNIEnv *jenv, jclass jcls) { + jstring jresult = NULL; + const char *result; + + result = pool_static_location(); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + return (jresult); +} + +/* + * pool_dynamic_location(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1dynamic_1location(JNIEnv * + jenv, jclass jcls) { + jstring jresult = NULL; + const char *result; + + result = pool_dynamic_location(); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + return (jresult); +} + +/* + * pool_set_binding(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1set_1binding(JNIEnv *jenv, + jclass jcls, jstring jpool, jint jidtype, jint jpid) { + const char *pool; + int result; + + pool = (jpool) ? (*jenv)->GetStringUTFChars(jenv, jpool, 0) : NULL; + result = (int)pool_set_binding(pool, (idtype_t)jidtype, (id_t)jpid); + + if (pool) + (*jenv)->ReleaseStringUTFChars(jenv, jpool, pool); + return ((jint)result); +} + +/* + * pool_get_binding(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1binding(JNIEnv *jenv, + jclass jcls, jint jpid) { + jstring jresult = NULL; + const char *result; + + result = pool_get_binding((pid_t)jpid); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + free((void *)result); + return (jresult); +} + +/* + * pool_get_resource_binding(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1resource_1binding( + JNIEnv *jenv, jclass jcls, jstring jtype, jint jpid) { + jstring jresult = NULL; + const char *type; + const char *result; + + type = (jtype) ? (*jenv)->GetStringUTFChars(jenv, jtype, 0) : NULL; + result = pool_get_resource_binding(type, (pid_t)jpid); + + if (result) + jresult = (*jenv)->NewStringUTF(jenv, result); + free((void *)result); + if (type) + (*jenv)->ReleaseStringUTFChars(jenv, jtype, type); + return (jresult); +} + +/* + * pool_walk_pools(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1pools(JNIEnv *jenv, + jclass jcls, jlong jconf, jlong jarg, jlong jcallback) { + int result; + + result = pool_walk_pools((pool_conf_t *)jconf, (void *)jarg, + (int (*)(pool_conf_t *, pool_t *, void *))jcallback); + return ((jint)result); +} + +/* + * pool_walk_resources(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1resources( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, jlong jarg, + jlong jcallback) { + int result; + + result = pool_walk_resources((pool_conf_t *)jconf, (pool_t *)jpool, + (void *)jarg, + (int (*)(pool_conf_t *, pool_resource_t *, void *))jcallback); + return ((jint)result); +} + +/* + * pool_walk_components(3pool) wrapper + */ +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1components( + JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource, jlong jarg, + jlong jcallback) { + int result; + + result = pool_walk_components((pool_conf_t *)jconf, + (pool_resource_t *)jresource, (void *)jarg, + (int (*)(pool_conf_t *, pool_component_t *, void *))jcallback); + return ((jint)result); +} + +/*ARGSUSED*/ +JNIEXPORT jint JNICALL +Java_com_sun_solaris_service_pools_Element_walkProps(JNIEnv *env, + jobject obj, jlong conf, jlong elem, jobject handler, jobject userobj) +{ + struct pool_callback pc; + + pc.pc_user = userobj; + pc.pc_handler = handler; + pc.pc_elem = obj; + pc.pc_env = env; + return (pool_walk_properties((pool_conf_t *)*(void**)&conf, + (pool_elem_t *)*(void**)&elem, (void *)&pc, pool_property_walker)); +} + +/*ARGSUSED*/ +static int +pool_property_walker(pool_conf_t *conf, pool_elem_t *pe, const char *name, + pool_value_t *pv, void *user) +{ + jclass clazz, vclazz; + jmethodID mgetwalk, mvcon; + struct pool_callback *pc = (struct pool_callback *)user; + jobject valueObj; + pool_value_t *pv_new; + uint64_t uval; + int64_t ival; + double dval; + uchar_t bval; + const char *sval; + + /* + * Since we intend to embed our value into a Java Value object + * and then reclaim the value when the object is garbage + * collected we must create a new pool value and then pass this + * to the constructor. We must not use the pool value which is + * passed to us. + */ + + if ((pv_new = pool_value_alloc()) == NULL) + return (PO_FAIL); + switch (pool_value_get_type(pv)) { + case POC_UINT: + (void) pool_value_get_uint64(pv, &uval); + (void) pool_value_set_uint64(pv_new, uval); + break; + case POC_INT: + (void) pool_value_get_int64(pv, &ival); + (void) pool_value_set_int64(pv_new, ival); + break; + case POC_DOUBLE: + (void) pool_value_get_double(pv, &dval); + (void) pool_value_set_double(pv_new, dval); + break; + case POC_BOOL: + (void) pool_value_get_bool(pv, &bval); + (void) pool_value_set_bool(pv_new, bval); + break; + case POC_STRING: + (void) pool_value_get_string(pv, &sval); + (void) pool_value_set_string(pv_new, sval); + break; + default: + pool_value_free(pv_new); + return (PO_FAIL); + } + if (pool_value_set_name(pv_new, name) != PO_SUCCESS || + (vclazz = (*pc->pc_env)->FindClass(pc->pc_env, + "com/sun/solaris/service/pools/Value")) == NULL || + (mvcon = (*pc->pc_env)->GetMethodID(pc->pc_env, vclazz, + "<init>", "(J)V")) == NULL || + (valueObj = (*pc->pc_env)->NewObject(pc->pc_env, vclazz, mvcon, + pv_new)) == NULL || + (clazz = (*pc->pc_env)->GetObjectClass(pc->pc_env, pc->pc_handler)) + == NULL || + (mgetwalk = (*pc->pc_env)->GetMethodID(pc->pc_env, + clazz, "walk", + "(Lcom/sun/solaris/service/pools/Element;Lcom/sun/solaris/" + "service/pools/Value;Ljava/lang/Object;)I")) == NULL) + return (PO_FAIL); + return ((*pc->pc_env)->CallIntMethod(pc->pc_env, + pc->pc_handler, mgetwalk, pc->pc_elem, valueObj, pc->pc_user)); +} + +/*ARGSUSED*/ +JNIEXPORT jlong JNICALL +Java_com_sun_solaris_service_pools_Value_getLongValue(JNIEnv *jenv, + jclass class, jlong pointer) +{ + int64_t arg2; + int result; + + result = pool_value_get_int64((pool_value_t *)pointer, &arg2); + + if (result != PO_SUCCESS) { /* it could be a uint64 */ + result = pool_value_get_uint64((pool_value_t *)pointer, + (uint64_t *)&arg2); + if (result != PO_SUCCESS) { + throw_pe(jenv); + } + /* + * Unfortunately, Java has no unsigned types, so we lose some + * precision by forcing the top bit clear + */ + arg2 &= 0x7fffffffffffffff; + } + return ((jlong)arg2); +} + +/*ARGSUSED*/ +JNIEXPORT jstring JNICALL +Java_com_sun_solaris_service_pools_Value_getStringValue(JNIEnv *jenv, + jclass class, jlong pointer) +{ + const char *arg2; + int result; + + result = pool_value_get_string((pool_value_t *)pointer, &arg2); + if (result != PO_SUCCESS) + throw_pe(jenv); + return ((*jenv)->NewStringUTF(jenv, arg2)); +} + +/*ARGSUSED*/ +JNIEXPORT jboolean JNICALL +Java_com_sun_solaris_service_pools_Value_getBoolValue(JNIEnv *jenv, + jclass class, jlong pointer) +{ + uchar_t arg2; + int result; + + result = pool_value_get_bool((pool_value_t *)pointer, &arg2); + + if (result != PO_SUCCESS) { + throw_pe(jenv); + } + if (arg2 == PO_TRUE) + return (JNI_TRUE); + else + return (JNI_FALSE); +} + +/*ARGSUSED*/ +JNIEXPORT jdouble JNICALL +Java_com_sun_solaris_service_pools_Value_getDoubleValue(JNIEnv *jenv, + jclass class, jlong pointer) +{ + double arg2; + int result; + + result = pool_value_get_double((pool_value_t *)pointer, &arg2); + + if (result != PO_SUCCESS) { + throw_pe(jenv); + } + return ((jdouble)arg2); +} + +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_Value_getUnsignedInt64Value(JNIEnv *jenv, + jclass class, jlong pointer) +{ + uint64_t arg2; + int result; + + result = pool_value_get_uint64((pool_value_t *)pointer, &arg2); + + if (result != PO_SUCCESS) { + throw_pe(jenv); + } + return (makeUnsignedInt64(jenv, arg2)); +} + +/*ARGSUSED*/ +JNIEXPORT jobject JNICALL +Java_com_sun_solaris_service_pools_HRTime_timestamp(JNIEnv *env, jobject obj) +{ + return (makeUnsignedInt64(env, gethrtime())); +} + +/* + * Cache class, method, and field IDs. + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_pools_PoolInternal_init(JNIEnv *env, jclass clazz) +{ + jclass ui64class_lref; + + if (!(ui64class_lref = (*env)->FindClass(env, + "com/sun/solaris/service/pools/UnsignedInt64"))) + return; /* exception thrown */ + if (!(ui64class = (*env)->NewGlobalRef(env, ui64class_lref))) + return; /* exception thrown */ + ui64cons_mid = (*env)->GetMethodID(env, ui64class, "<init>", "([B)V"); +} diff --git a/usr/src/cmd/pools/poold/libjpool/sparc/Makefile b/usr/src/cmd/pools/poold/libjpool/sparc/Makefile new file mode 100644 index 0000000000..c362cddcde --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/sparc/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/sparc/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/sparc + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjpool/spec/Makefile b/usr/src/cmd/pools/poold/libjpool/spec/Makefile new file mode 100644 index 0000000000..ac42336aea --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec/Makefile +# + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/cmd/pools/poold/libjpool/spec/Makefile.targ b/usr/src/cmd/pools/poold/libjpool/spec/Makefile.targ new file mode 100644 index 0000000000..1fecfd654a --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/Makefile.targ @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec/Makefile.targ +# + +.KEEP_STATE: + +LIBRARY = libjpool.a +VERS = .1 + +OBJECTS = jpool.o diff --git a/usr/src/cmd/pools/poold/libjpool/spec/amd64/Makefile b/usr/src/cmd/pools/poold/libjpool/spec/amd64/Makefile new file mode 100644 index 0000000000..aa209263c6 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/amd64/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP64) diff --git a/usr/src/cmd/pools/poold/libjpool/spec/i386/Makefile b/usr/src/cmd/pools/poold/libjpool/spec/i386/Makefile new file mode 100644 index 0000000000..616e85b404 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/i386/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjpool/spec/jpool.spec b/usr/src/cmd/pools/poold/libjpool/spec/jpool.spec new file mode 100644 index 0000000000..faeabb575e --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/jpool.spec @@ -0,0 +1,760 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# "../../jpool.h" + +function Java_com_sun_solaris_service_pools_Value_getUnsignedInt64Value +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_Value_getUnsignedInt64Value \ + (JNIEnv *jenv, jclass class, jlong pointer) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1bool +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1bool \ + (JNIEnv *jenv, jclass jcls, jlong jvalue, jshort jb) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1get_1type +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1get_1type \ + (JNIEnv *jenv, jclass jcls, jlong jvalue) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1INVAL +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1INVAL \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1info +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1info \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, \ + jint jflags) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1rm_1property +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1rm_1property \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, \ + jstring jname) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1DESTROY +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1DESTROY \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1properties +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1properties \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, \ + jlong jarg, jlong jcallback) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1INVALID +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1INVALID \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1NONE +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1NONE \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_Value_getDoubleValue +include "../../jpool.h" +declaration jdouble \ + Java_com_sun_solaris_service_pools_Value_getDoubleValue \ + (JNIEnv *jenv, jclass class, jlong pointer) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1to_1elem +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1to_1elem \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1static_1location +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1static_1location \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1INT +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1INT \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1rollback +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1rollback \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1status +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1status \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_Value_getBoolValue +include "../../jpool.h" +declaration jboolean \ + Java_com_sun_solaris_service_pools_Value_getBoolValue \ + (JNIEnv *jenv, jclass class, jlong pointer) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1components +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1components \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource, \ + jlong jarg, jlong jcallback) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1version +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1version \ + (JNIEnv *jenv, jclass jcls, jlong jver) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1name +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1name \ + (JNIEnv *jenv, jclass jcls, jlong jvalue, jstring jname) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1free +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1free \ + (JNIEnv *jenv, jclass jcls, jlong jvalue) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1set_1status +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1set_1status \ + (JNIEnv *jenv, jclass jcls, jint jstate) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1xtransfer +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1xtransfer \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jsource, \ + jlong jtarget, jobject jcomponents) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1DOUBLE +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1DOUBLE \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1VALID +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POF_1VALID \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1alloc +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1alloc \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1resources +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1resources \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jobject jprops) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_Value_getLongValue +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_Value_getLongValue \ + (JNIEnv *jenv, jclass class, jlong pointer) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1strerror_1sys +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1strerror_1sys \ + (JNIEnv * jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1destroy +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1destroy \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1property +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1property \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, \ + jstring jname, jlong jproperty) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1dynamic_1location +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1dynamic_1location \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1component_1to_1elem +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1component_1to_1elem \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jcomponent) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1status +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1status \ + (JNIEnv *jenv, jclass jcls, jlong jstatep) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1LOOSE +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1LOOSE \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_HRTime_timestamp +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_HRTime_timestamp \ + (JNIEnv *env, jobject obj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1info +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1info \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource, \ + jint jflags) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1alloc +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1alloc \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1STRING +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1STRING \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1create +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1create \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jstring jname) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1owning_1resource +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1owning_1resource \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jcomponent) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_init +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_init \ + (JNIEnv *env, jclass clazz) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_Value_getStringValue +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_Value_getStringValue \ + (JNIEnv *jenv, jclass class, jlong pointer) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1resources +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1resources \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, \ + jlong jarg, jlong jcallback) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1set_1binding +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1set_1binding \ + (JNIEnv *jenv, jclass jcls, jstring jpool, jint jidtype, \ + jint jpid) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1info +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1info \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jint jflags) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POX_1NATIVE +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POX_1NATIVE \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1validate +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1validate \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jint jlevel) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1resource +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1resource \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jstring jtype, \ + jstring jname) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1dissociate +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1dissociate \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, \ + jlong jresource) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolsException_getErrno +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolsException_getErrno \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1to_1elem +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1to_1elem \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1pools +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1pools \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jobject jprops) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1resource_1components +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1resource_1components \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong resource, \ + jobject jprops) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POX_1TEXT +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POX_1TEXT \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1location +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1location \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1close +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1close \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1associate +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1associate \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, \ + jlong jresource) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1put_1property +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1put_1property \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jelem, \ + jstring jname, jlong jvalue) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1resource_1binding +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1resource_1binding \ + (JNIEnv *jenv, jclass jcls, jstring jtype, jint jpid) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1int64 +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1int64 \ + (JNIEnv *jenv, jclass jcls, jlong jvalue, jlong ji64) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1type_1list +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1type_1list \ + (JNIEnv *jenv, jclass jcls, jlong jreslist, jlong jnumres) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1destroy +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1destroy \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1pool +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1pool \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jstring jname) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1commit +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1commit \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jint jactive) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1uint64 +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1uint64 \ + (JNIEnv *jenv, jclass jcls, jlong jvalue, jlong jui64) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1double +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1double \ + (JNIEnv *jenv, jclass jcls, jlong jvalue, jdouble jd) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1get_1name +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1get_1name \ + (JNIEnv *jenv, jclass jcls, jlong jvalue) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1UINT +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1UINT \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1remove +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1remove \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1STRICT +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1STRICT \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_Element_walkProps +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_Element_walkProps \ + (JNIEnv *env, jobject obj, jlong conf, jlong elem, \ + jobject handler, jobject userobj) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1open +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1open \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jstring jlocation, \ + jint jflags) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1free +include "../../jpool.h" +declaration void \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1free \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1error +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1error \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1transfer +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1transfer \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jsource, \ + jlong jtarget, jlong jsize) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1to_1elem +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1to_1elem \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jresource) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1update +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1update \ + (JNIEnv *jenv, jclass jcls, jlong jconf) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1pools +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1walk_1pools \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jarg, \ + jlong jcallback) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1create +include "../../jpool.h" +declaration jlong \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1resource_1create \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jstring jtype, \ + jstring jname) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1RUNTIME +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POV_1RUNTIME \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1component_1info +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1component_1info \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jcomponent, \ + jint jflags) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1binding +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1get_1binding \ + (JNIEnv *jenv, jclass jcls, jint jpid) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1strerror +include "../../jpool.h" +declaration jstring \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1strerror \ + (JNIEnv *jenv, jclass jcls, jint jperr) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1BOOL +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_get_1POC_1BOOL \ + (JNIEnv *jenv, jclass jcls) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1string +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1value_1set_1string \ + (JNIEnv * jenv, jclass jcls, jlong jvalue, jstring jstr) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1pool_1resources +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1pool_1resources \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jlong jpool, jobject jprops) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1export +include "../../jpool.h" +declaration jint \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1conf_1export \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jstring jlocation, \ + jint jformat) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1components +include "../../jpool.h" +declaration jobject \ + Java_com_sun_solaris_service_pools_PoolInternal_pool_1query_1components \ + (JNIEnv *jenv, jclass jcls, jlong jconf, jobject jprops) +version SUNWprivate_1.1 +end diff --git a/usr/src/cmd/pools/poold/libjpool/spec/sparc/Makefile b/usr/src/cmd/pools/poold/libjpool/spec/sparc/Makefile new file mode 100644 index 0000000000..00d0224208 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/sparc/Makefile @@ -0,0 +1,41 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjpool/spec/sparcv9/Makefile b/usr/src/cmd/pools/poold/libjpool/spec/sparcv9/Makefile new file mode 100644 index 0000000000..d7de5d0445 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/sparcv9/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec/sparcv9/Makefile + +DISABLE_APPTRACE= $(POUND_SIGN) +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 +include $(SRC)/lib/Makefile.spec + +$(DISABLE_APPTRACE)install: $(ROOTABILIB64) diff --git a/usr/src/cmd/pools/poold/libjpool/spec/versions b/usr/src/cmd/pools/poold/libjpool/spec/versions new file mode 100644 index 0000000000..88bc34e512 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjpool/spec/versions @@ -0,0 +1,36 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjpool/spec versions +# + +i386 { + SUNWprivate_1.1; +} + +sparc { + SUNWprivate_1.1; +} diff --git a/usr/src/cmd/pools/poold/libjsyslog/Makefile b/usr/src/cmd/pools/poold/libjsyslog/Makefile new file mode 100644 index 0000000000..c668a01be3 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/Makefile @@ -0,0 +1,62 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/Makefile +# + +include $(SRC)/lib/Makefile.lib + +SUBDIRS = spec .WAIT $(MACH) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +JNI_CLASSES = \ + com.sun.solaris.service.logging.SyslogHandler + +JNI_GENERATED_HEADERS = \ + jsyslog.h + +CLEANFILES += $(JNI_GENERATED_HEADERS) + +all install lint: $(JNI_GENERATED_HEADERS) .WAIT $(SUBDIRS) + +clean clobber: $(SUBDIRS) + +$(JNI_GENERATED_HEADERS): $(SRC)/cmd/pools/poold/JPool.jar + $(JAVAH) -classpath $? -o $@ $(JNI_CLASSES) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include $(SRC)/lib/Makefile.targ +include $(SRC)/Makefile.msg.targ diff --git a/usr/src/cmd/pools/poold/libjsyslog/Makefile.com b/usr/src/cmd/pools/poold/libjsyslog/Makefile.com new file mode 100644 index 0000000000..eec6efccfa --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/Makefile.com @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/Makefile.com +# + +LIBRARY = libjsyslog.a +VERS = .1 + +OBJECTS = jsyslog.o + +include $(SRC)/lib/Makefile.lib + +INCS = -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris +MAPFILE = $(MAPDIR)/mapfile + +LIBS = $(DYNLIB) +LDLIBS += -lc +DYNFLAGS += -M$(MAPFILE) +ROOTLIBDIR = $(ROOT)/usr/lib/pool +SRCDIR = $(SRC)/cmd/pools/poold/libjsyslog + +CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64 $(INCS) + +all: $(LIBS) + +lint: lintcheck + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/cmd/pools/poold/libjsyslog/i386/Makefile b/usr/src/cmd/pools/poold/libjsyslog/i386/Makefile new file mode 100644 index 0000000000..c47e40e1d6 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/i386/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/i386/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/i386 + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjsyslog/jsyslog.c b/usr/src/cmd/pools/poold/libjsyslog/jsyslog.c new file mode 100644 index 0000000000..5bd119e281 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/jsyslog.c @@ -0,0 +1,113 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stddef.h> +#include <assert.h> +#include <string.h> +#include <syslog.h> + +#include "jsyslog.h" + +#define ILL_ARG_EX_CLASS_DESC "java/lang/IllegalArgumentException" +#define THROWABLE_CLASS_DESC "java/lang/Throwable" + +#define CLASS_FIELD_DESC(class_desc) "L" class_desc ";" + +/* + * syslog(3c) ident string + */ +static char jsyslog_ident[32]; + +/* + * Log the given message with the given severity. + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_logging_SyslogHandler_syslog(JNIEnv *env, + jclass clazz, jint severity, jstring messageObj) +{ + const char *message; + + if (messageObj == NULL) { + jclass exceptionClass; + + if (!(exceptionClass = (*env)->FindClass(env, + ILL_ARG_EX_CLASS_DESC))) + return; /* exception thrown */ + (*env)->Throw(env, (*env)->NewObject(env, exceptionClass, + (*env)->GetStaticMethodID(env, exceptionClass, "<init>", + "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); + return; + } + + if (!(message = (*env)->GetStringUTFChars(env, messageObj, NULL))) + return; /* exception thrown */ + syslog(severity, "%s", message); + (*env)->ReleaseStringUTFChars(env, messageObj, message); +} + +/* + * Invoke openlog(3c). + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_logging_SyslogHandler_openlog(JNIEnv *env, + jclass clazz, jstring identObj, jint logopt, jint facility) +{ + const char *ident; + + if (identObj == NULL) { + jclass exceptionClass; + + if (!(exceptionClass = (*env)->FindClass(env, + ILL_ARG_EX_CLASS_DESC))) + return; /* exception thrown */ + (*env)->Throw(env, (*env)->NewObject(env, exceptionClass, + (*env)->GetStaticMethodID(env, exceptionClass, "<init>", + "()" CLASS_FIELD_DESC(THROWABLE_CLASS_DESC)))); + return; + } + + if (!(ident = (*env)->GetStringUTFChars(env, identObj, NULL))) + return; /* exception thrown */ + (void) strlcpy(jsyslog_ident, ident, sizeof (jsyslog_ident)); + openlog(jsyslog_ident, logopt, facility); + + (*env)->ReleaseStringUTFChars(env, identObj, ident); +} + +/* + * Invoke closelog(3c). + */ +/*ARGSUSED*/ +JNIEXPORT void JNICALL +Java_com_sun_solaris_service_logging_SyslogHandler_closelog(JNIEnv *env, + jclass clazz) +{ + closelog(); +} diff --git a/usr/src/cmd/pools/poold/libjsyslog/sparc/Makefile b/usr/src/cmd/pools/poold/libjsyslog/sparc/Makefile new file mode 100644 index 0000000000..73c4c909f0 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/sparc/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/sparc/Makefile +# + + +include ../Makefile.com + +MAPDIR= ../spec/sparc + +install: all $(ROOTLIBS) $(ROOTLINKS) diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/Makefile b/usr/src/cmd/pools/poold/libjsyslog/spec/Makefile new file mode 100644 index 0000000000..7f90194f7a --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/Makefile +# + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/Makefile.targ b/usr/src/cmd/pools/poold/libjsyslog/spec/Makefile.targ new file mode 100644 index 0000000000..902097f7f3 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/Makefile.targ @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/Makefile.targ +# + +.KEEP_STATE: + +LIBRARY = libjsyslog.a +VERS = .1 + +OBJECTS = jsyslog.o diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/amd64/Makefile b/usr/src/cmd/pools/poold/libjsyslog/spec/amd64/Makefile new file mode 100644 index 0000000000..834ae5533d --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/amd64/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 + +include $(SRC)/lib/Makefile.spec + +CFLAGS64 += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP64) diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/i386/Makefile b/usr/src/cmd/pools/poold/libjsyslog/spec/i386/Makefile new file mode 100644 index 0000000000..d3a8371369 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/i386/Makefile @@ -0,0 +1,42 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/i386/Makefile +# + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/jsyslog.spec b/usr/src/cmd/pools/poold/libjsyslog/spec/jsyslog.spec new file mode 100644 index 0000000000..090b4de9bd --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/jsyslog.spec @@ -0,0 +1,53 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/jsyslog.spec + +function Java_com_sun_solaris_service_logging_SyslogHandler_closelog +include "../../jsyslog.h" +declaration void \ + Java_com_sun_solaris_service_logging_SyslogHandler_closelog \ + (JNIEnv *env, jclass clazz) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_logging_SyslogHandler_openlog +include "../../jsyslog.h" +declaration void \ + Java_com_sun_solaris_service_logging_SyslogHandler_openlog \ + (JNIEnv *env, jclass clazz, jstring identObj, jint logopt, \ + jint facility) +version SUNWprivate_1.1 +end + +function Java_com_sun_solaris_service_logging_SyslogHandler_syslog +include "../../jsyslog.h" +declaration void \ + Java_com_sun_solaris_service_logging_SyslogHandler_syslog \ + (JNIEnv *env, jclass clazz, jint severity, jstring messageObj) +version SUNWprivate_1.1 +end + diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/sparc/Makefile b/usr/src/cmd/pools/poold/libjsyslog/spec/sparc/Makefile new file mode 100644 index 0000000000..57a87c60a4 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/sparc/Makefile @@ -0,0 +1,41 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/sparc/Makefile + +.KEEP_STATE: + +include ../Makefile.targ + +include $(SRC)/lib/Makefile.lib + +include $(SRC)/lib/Makefile.spec + +CFLAGS += -I$(JAVA_ROOT)/include \ + -I$(JAVA_ROOT)/include/solaris + +install: $(SPECMAP) diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/sparcv9/Makefile b/usr/src/cmd/pools/poold/libjsyslog/spec/sparcv9/Makefile new file mode 100644 index 0000000000..754d9ca943 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/sparcv9/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec/sparcv9/Makefile + +DISABLE_APPTRACE= $(POUND_SIGN) +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 +include $(SRC)/lib/Makefile.spec + +$(DISABLE_APPTRACE)install: $(ROOTABILIB64) diff --git a/usr/src/cmd/pools/poold/libjsyslog/spec/versions b/usr/src/cmd/pools/poold/libjsyslog/spec/versions new file mode 100644 index 0000000000..e1a5cf94b6 --- /dev/null +++ b/usr/src/cmd/pools/poold/libjsyslog/spec/versions @@ -0,0 +1,36 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#pragma ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poold/libjsyslog/spec versions +# + +i386 { + SUNWprivate_1.1; +} + +sparc { + SUNWprivate_1.1; +} diff --git a/usr/src/cmd/pools/poold/poold.c b/usr/src/cmd/pools/poold/poold.c new file mode 100644 index 0000000000..0d12d5a832 --- /dev/null +++ b/usr/src/cmd/pools/poold/poold.c @@ -0,0 +1,680 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * poold - dynamically adjust pool configuration according to load. + */ +#include <errno.h> +#include <jni.h> +#include <libintl.h> +#include <limits.h> +#include <link.h> +#include <locale.h> +#include <poll.h> +#include <pool.h> +#include <priv.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ucontext.h> +#include "utils.h" + +#define POOLD_DEF_CLASSPATH "/usr/lib/pool/JPool.jar" +#define POOLD_DEF_LIBPATH "/usr/lib/pool" + +#if defined(sparc) +#define PLAT "sparc" +#else +#if defined(i386) +#define PLAT "i386" +#else +#error Unrecognized platform. +#endif +#endif + +#define PID_PROPERTY_NAME "system.poold.pid" + +#define CLASS_FIELD_DESC(class_desc) "L" class_desc ";" + +#define LEVEL_CLASS_DESC "java/util/logging/Level" +#define POOLD_CLASS_DESC "com/sun/solaris/domain/pools/Poold" +#define SEVERITY_CLASS_DESC "com/sun/solaris/service/logging/Severity" +#define STRING_CLASS_DESC "java/lang/String" +#define SYSTEM_CLASS_DESC "java/lang/System" +#define LOGGER_CLASS_DESC "java/util/logging/Logger" + +extern char *optarg; + +static const char *pname; + +static enum { + LD_TERMINAL = 1, + LD_SYSLOG, + LD_JAVA +} log_dest = LD_SYSLOG; + +typedef enum { + PGAS_GET_ONLY = 1, + PGAS_GET_AND_SET +} pgas_mode_t; + +static const char PNAME_FMT[] = "%s: "; +static const char ERRNO_FMT[] = ": %s"; + +static JavaVM *jvm; +static int lflag; + +static jmethodID log_mid; +static jobject severity_err; +static jobject severity_notice; +static jobject base_log; +static jclass poold_class; +static jobject poold_instance; +static int instance_running; +static pthread_mutex_t instance_running_lock = PTHREAD_MUTEX_INITIALIZER; + +static sigset_t hdl_set; + +static void +usage(void) +{ + (void) fprintf(stderr, gettext("Usage:\t%s [-l <level>]\n"), pname); + + exit(E_USAGE); +} + +static void +pu_output(int severity, const char *fmt, va_list alist) +{ + int err = errno; + char line[255] = ""; + jobject jseverity; + jobject jline; + JNIEnv *env; + int detach_required = 0; + if (pname != NULL && log_dest == LD_TERMINAL) + (void) snprintf(line, sizeof (line), gettext(PNAME_FMT), pname); + + (void) vsnprintf(line + strlen(line), sizeof (line) - strlen(line), + fmt, alist); + + if (line[strlen(line) - 1] != '\n') + (void) snprintf(line + strlen(line), sizeof (line) - + strlen(line), gettext(ERRNO_FMT), strerror(err)); + else + line[strlen(line) - 1] = 0; + + switch (log_dest) { + case LD_TERMINAL: + (void) fprintf(stderr, "%s\n", line); + (void) fflush(stderr); + break; + case LD_SYSLOG: + syslog(LOG_ERR, "%s", line); + break; + case LD_JAVA: + if (severity == LOG_ERR) + jseverity = severity_err; + else + jseverity = severity_notice; + + if (jvm) { + (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2); + if (env == NULL) { + detach_required = 1; + (*jvm)->AttachCurrentThread(jvm, + (void **)&env, NULL); + } + if ((jline = (*env)->NewStringUTF(env, line)) != NULL) + (*env)->CallVoidMethod(env, base_log, log_mid, + jseverity, jline); + if (detach_required) + (*jvm)->DetachCurrentThread(jvm); + } + } +} + +/*PRINTFLIKE1*/ +static void +pu_notice(const char *fmt, ...) +{ + va_list alist; + va_start(alist, fmt); + pu_output(LOG_NOTICE, fmt, alist); + va_end(alist); +} + +/*PRINTFLIKE1*/ +static void +pu_die(const char *fmt, ...) +{ + va_list alist; + va_start(alist, fmt); + pu_output(LOG_ERR, fmt, alist); + va_end(alist); + exit(E_ERROR); +} + +/* + * Update the "system.poold.pid" to reflect this instance of poold only + * if the property hasn't been set already to reflect an existing + * process, and mode is not set to PGAS_GET_ONLY. Returns the + * property's pre-existing value, or -1 otherwise. + */ +static pid_t +poold_get_and_set_pid(pgas_mode_t mode) +{ + pool_conf_t *conf; + pool_elem_t *pe; + pool_value_t *val; + int64_t ival; + + if (!(conf = pool_conf_alloc())) + return ((pid_t)-1); + + if (pool_conf_open(conf, pool_dynamic_location(), PO_RDWR) != 0) { + (void) pool_conf_free(conf); + return ((pid_t)-1); + } + + pe = pool_conf_to_elem(conf); + if (!(val = pool_value_alloc())) { + (void) pool_conf_close(conf); + return ((pid_t)-1); + } + + if (pool_get_property(conf, pe, PID_PROPERTY_NAME, val) == POC_INT) { + if (pool_value_get_int64(val, &ival) != 0) { + (void) pool_value_free(val); + (void) pool_conf_close(conf); + return ((pid_t)-1); + } + } else { + ival = (pid_t)-1; + } + + if (mode == PGAS_GET_AND_SET) { + ival = getpid(); + pool_value_set_int64(val, ival); + (void) pool_put_property(conf, pe, PID_PROPERTY_NAME, val); + (void) pool_conf_commit(conf, 0); + } + + (void) pool_value_free(val); + (void) pool_conf_close(conf); + pool_conf_free(conf); + + return ((pid_t)ival); +} + +/* + * Reconfigure the JVM by simply updating a dummy property on the + * system element to force pool_conf_update() to detect a change. + */ +static void +reconfigure() +{ + JNIEnv *env; + pool_conf_t *conf; + pool_elem_t *pe; + pool_value_t *val; + const char *err_desc; + int detach_required = 0; + + if ((conf = pool_conf_alloc()) == NULL) { + err_desc = pool_strerror(pool_error()); + goto destroy; + } + if (pool_conf_open(conf, pool_dynamic_location(), PO_RDWR) != 0) { + err_desc = pool_strerror(pool_error()); + pool_conf_free(conf); + goto destroy; + } + + if ((val = pool_value_alloc()) == NULL) { + err_desc = pool_strerror(pool_error()); + (void) pool_conf_close(conf); + pool_conf_free(conf); + goto destroy; + } + pe = pool_conf_to_elem(conf); + pool_value_set_bool(val, 1); + if (pool_put_property(conf, pe, "system.poold.sighup", val) != + PO_SUCCESS) { + err_desc = pool_strerror(pool_error()); + pool_value_free(val); + (void) pool_conf_close(conf); + pool_conf_free(conf); + goto destroy; + } + pool_value_free(val); + (void) pool_rm_property(conf, pe, "system.poold.sighup"); + if (pool_conf_commit(conf, 0) != PO_SUCCESS) { + err_desc = pool_strerror(pool_error()); + (void) pool_conf_close(conf); + pool_conf_free(conf); + goto destroy; + } + (void) pool_conf_close(conf); + pool_conf_free(conf); + return; +destroy: + if (jvm) { + (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2); + if (env == NULL) { + detach_required = 1; + (*jvm)->AttachCurrentThread(jvm, (void **)&env, NULL); + } + if (lflag && (*env)->ExceptionOccurred(env)) + (*env)->ExceptionDescribe(env); + if (detach_required) + (*jvm)->DetachCurrentThread(jvm); + (*jvm)->DestroyJavaVM(jvm); + } + pu_die(err_desc); +} + +/* + * If SIGHUP is invoked, we should just re-initialize poold. Since + * there is no easy way to determine when it's safe to re-initialzie + * poold, simply update a dummy property on the system element to + * force pool_conf_update() to detect a change. + * + * Both SIGTERM and SIGINT are interpreted as instructions to + * shutdown. + */ +/*ARGSUSED*/ +static void * +handle_sig(void *arg) +{ + for (;;) { + JNIEnv *env; + jmethodID poold_shutdown_mid; + int sig; + char buf[SIG2STR_MAX]; + int detach_required = 0; + + if ((sig = sigwait(&hdl_set)) < 0) + pu_die("unexpected error: %d\n", errno); + (void) sig2str(sig, buf); + switch (sig) { + case SIGHUP: + reconfigure(); + break; + case SIGINT: + case SIGTERM: + (void) pthread_mutex_lock(&instance_running_lock); + if (instance_running) { + (void) pthread_mutex_unlock( + &instance_running_lock); + (*jvm)->GetEnv(jvm, (void **)&env, + JNI_VERSION_1_2); + if (env == NULL) { + detach_required = 1; + (*jvm)->AttachCurrentThread(jvm, + (void **)&env, NULL); + } + pu_notice("terminating due to signal: SIG%s\n", + buf); + if ((poold_shutdown_mid = (*env)->GetMethodID( + env, poold_class, "shutdown", "()V")) != + NULL) { + (*env)->CallVoidMethod(env, + poold_instance, + poold_shutdown_mid); + } else { + (*env)->ExceptionDescribe(env); + pu_die("could not invoke" + " proper shutdown\n"); + } + if (detach_required) + (*jvm)->DetachCurrentThread(jvm); + } else { + (void) pthread_mutex_unlock( + &instance_running_lock); + pu_die("terminated with signal: SIG%s\n", buf); + /*NOTREACHED*/ + } + break; + default: + pu_die("unexpected signal: SIG%s\n", buf); + } + } + /*NOTREACHED*/ + return (NULL); +} + +static const char * +pu_getpname(const char *arg0) +{ + char *p; + + /* + * Guard against '/' at end of command invocation. + */ + for (;;) { + p = strrchr(arg0, '/'); + if (p == NULL) { + pname = arg0; + break; + } else { + if (*(p + 1) == '\0') { + *p = '\0'; + continue; + } + + pname = p + 1; + break; + } + } + + return (pname); +} + +int +main(int argc, char *argv[]) +{ + char c; + char log_severity[16] = ""; + pid_t pid; + JavaVMInitArgs vm_args; + JavaVMOption vm_opts[5]; + int nopts = 0; + const char *classpath; + const char *libpath; + size_t len; + const char *err_desc; + JNIEnv *env; + jmethodID poold_getinstancewcl_mid; + jmethodID poold_run_mid; + jobject log_severity_string = NULL; + jobject log_severity_obj = NULL; + jclass severity_class; + jmethodID severity_cons_mid; + jfieldID base_log_fid; + int explain_ex = 1; + JavaVM *jvm_tmp; + pthread_t hdl_thread; + + pname = pu_getpname(argv[0]); + openlog(pname, 0, LOG_DAEMON); + (void) chdir("/"); + + (void) setlocale(LC_ALL, ""); +#if !defined(TEXT_DOMAIN) /* Should be defined with cc -D. */ +#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't. */ +#endif + (void) textdomain(TEXT_DOMAIN); + + opterr = 0; + while ((c = getopt(argc, argv, "l:P")) != EOF) { + switch (c) { + case 'l': /* -l option */ + lflag++; + (void) strlcpy(log_severity, optarg, + sizeof (log_severity)); + log_dest = LD_TERMINAL; + break; + default: + usage(); + /*NOTREACHED*/ + } + } + + /* + * Verify no other poold is running. This condition is checked + * again later, but should be checked now since it is more + * serious (i.e. should be reported before) than a lack of + * privileges. + */ + if (((pid = poold_get_and_set_pid(PGAS_GET_ONLY)) != (pid_t)-1) && + pid != getpid() && kill(pid, 0) == 0) + pu_die(gettext("poold is already active (process %ld)\n"), pid); + + /* + * Check permission + */ + if (!priv_ineffect(PRIV_SYS_RES_CONFIG)) + pu_die(gettext(ERR_PRIVILEGE), PRIV_SYS_RES_CONFIG); + + /* + * Establish the classpath and LD_LIBRARY_PATH for native + * methods, and get the interpreter going. + */ + if ((classpath = getenv("POOLD_CLASSPATH")) == NULL) { + classpath = POOLD_DEF_CLASSPATH; + } else { + const char *cur = classpath; + + /* + * Check the components to make sure they're absolute + * paths. + */ + while (cur != NULL && *cur) { + if (*cur != '/') + pu_die(gettext( + "POOLD_CLASSPATH must contain absolute " + "components\n")); + cur = strchr(cur + 1, ':'); + } + } + vm_opts[nopts].optionString = malloc(len = strlen(classpath) + + strlen("-Djava.class.path=") + 1); + (void) strlcpy(vm_opts[nopts].optionString, "-Djava.class.path=", len); + (void) strlcat(vm_opts[nopts++].optionString, classpath, len); + + if ((libpath = getenv("POOLD_LD_LIBRARY_PATH")) == NULL) + libpath = POOLD_DEF_LIBPATH; + vm_opts[nopts].optionString = malloc(len = strlen(libpath) + + strlen("-Djava.library.path=") + 1); + (void) strlcpy(vm_opts[nopts].optionString, "-Djava.library.path=", + len); + (void) strlcat(vm_opts[nopts++].optionString, libpath, len); + + vm_opts[nopts++].optionString = "-Xrs"; + vm_opts[nopts++].optionString = "-enableassertions"; + + vm_args.options = vm_opts; + vm_args.nOptions = nopts; + vm_args.ignoreUnrecognized = JNI_FALSE; + vm_args.version = 0x00010002; + + /* + * XXX - Forking after the VM is created is desirable to + * guarantee reporting of errors, but cannot be done (see + * 4919246). + * + * If invoked by libpool(3LIB), it's set the system.poold.pid + * property and forked already. If invoked directly and -l is + * specified, forking is not desired. + */ + if (!lflag && pid != getpid()) + switch (fork()) { + case 0: + (void) setsid(); + (void) fclose(stdin); + (void) fclose(stdout); + (void) fclose(stderr); + break; + case -1: + pu_die(gettext("cannot fork")); + /*NOTREACHED*/ + default: + return (E_PO_SUCCESS); + } + + /* + * In order to avoid problems with arbitrary thread selection + * when handling asynchronous signals, dedicate a thread to + * look after these signals. + */ + if (sigemptyset(&hdl_set) < 0 || + sigaddset(&hdl_set, SIGHUP) < 0 || + sigaddset(&hdl_set, SIGTERM) < 0 || + sigaddset(&hdl_set, SIGINT) < 0 || + pthread_sigmask(SIG_BLOCK, &hdl_set, NULL) || + pthread_create(&hdl_thread, NULL, handle_sig, NULL)) + pu_die(gettext("can't install signal handler")); + + /* + * Use jvm_tmp when creating the jvm to prevent race + * conditions with signal handlers. As soon as the call + * returns, assign the global jvm to jvm_tmp. + */ + if (JNI_CreateJavaVM(&jvm_tmp, (void **)&env, &vm_args) < 0) + pu_die(gettext("can't create Java VM")); + jvm = jvm_tmp; + + /* + * Locate the Poold class and construct an instance. A side + * effect of this is that the poold instance's logHelper will be + * initialized, establishing loggers for logging errors from + * this point on. (Note, in the event of an unanticipated + * exception, poold will invoke die() itself.) + */ + err_desc = gettext("JVM-related error initializing poold\n"); + if ((poold_class = (*env)->FindClass(env, POOLD_CLASS_DESC)) == NULL) + goto destroy; + if ((poold_getinstancewcl_mid = (*env)->GetStaticMethodID(env, + poold_class, "getInstanceWithConsoleLogging", "(" + CLASS_FIELD_DESC(SEVERITY_CLASS_DESC) ")" + CLASS_FIELD_DESC(POOLD_CLASS_DESC))) == NULL) + goto destroy; + if ((poold_run_mid = (*env)->GetMethodID(env, poold_class, "run", + "()V")) == NULL) + goto destroy; + if ((severity_class = (*env)->FindClass(env, SEVERITY_CLASS_DESC)) + == NULL) + goto destroy; + if ((severity_cons_mid = (*env)->GetStaticMethodID(env, severity_class, + "getSeverityWithName", "(" CLASS_FIELD_DESC(STRING_CLASS_DESC) ")" + CLASS_FIELD_DESC(SEVERITY_CLASS_DESC))) == NULL) + goto destroy; + + /* + * -l <level> was specified, indicating that messages are to be + * logged to the console only. + */ + if (strlen(log_severity) > 0) { + if ((log_severity_string = (*env)->NewStringUTF(env, + log_severity)) == NULL) + goto destroy; + if ((log_severity_obj = (*env)->CallStaticObjectMethod(env, + severity_class, severity_cons_mid, log_severity_string)) == + NULL) { + err_desc = gettext("invalid level specified\n"); + explain_ex = 0; + goto destroy; + } + } else + log_severity_obj = NULL; + + if ((poold_instance = (*env)->CallStaticObjectMethod(env, poold_class, + poold_getinstancewcl_mid, log_severity_obj)) == NULL) + goto destroy; + + /* + * Grab a global reference to poold for use in our signal + * handlers. + */ + poold_instance = (*env)->NewGlobalRef(env, poold_instance); + + /* + * Ready LD_JAVA logging. + */ + err_desc = gettext("cannot initialize logging\n"); + if ((log_severity_string = (*env)->NewStringUTF(env, "err")) == NULL) + goto destroy; + if (!(severity_err = (*env)->CallStaticObjectMethod(env, severity_class, + severity_cons_mid, log_severity_string))) + goto destroy; + if (!(severity_err = (*env)->NewGlobalRef(env, severity_err))) + goto destroy; + + if ((log_severity_string = (*env)->NewStringUTF(env, "notice")) == NULL) + goto destroy; + if (!(severity_notice = (*env)->CallStaticObjectMethod(env, + severity_class, severity_cons_mid, log_severity_string))) + goto destroy; + if (!(severity_notice = (*env)->NewGlobalRef(env, severity_notice))) + goto destroy; + + if (!(base_log_fid = (*env)->GetStaticFieldID(env, poold_class, + "BASE_LOG", CLASS_FIELD_DESC(LOGGER_CLASS_DESC)))) + goto destroy; + if (!(base_log = (*env)->GetStaticObjectField(env, poold_class, + base_log_fid))) + goto destroy; + if (!(base_log = (*env)->NewGlobalRef(env, base_log))) + goto destroy; + if (!(log_mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, + base_log), "log", "(" CLASS_FIELD_DESC(LEVEL_CLASS_DESC) + CLASS_FIELD_DESC(STRING_CLASS_DESC) ")V"))) + goto destroy; + log_dest = LD_JAVA; + + /* + * Now we're ready to start poold. Store our pid in the pools + * configuration to mark that an instance of poold is active, + * then invoke Poold.run(), which does not normally return. + * + * Note that the ignoreUpdates variable in Poold is used to + * allow Poold to ignore the pools configuration update that + * this change triggers. If this code is ever modified to + * remove or modify this logic, then the Poold class must also + * be modified to keep the actions synchronized. + */ + + if (((pid = poold_get_and_set_pid(PGAS_GET_AND_SET)) != (pid_t)-1) && + pid != getpid() && kill(pid, 0) == 0) + pu_die(gettext("poold is already active (process %ld)\n"), pid); + + (void) pthread_mutex_lock(&instance_running_lock); + instance_running = 1; + (void) pthread_mutex_unlock(&instance_running_lock); + (*env)->CallVoidMethod(env, poold_instance, poold_run_mid); + + if ((*env)->ExceptionOccurred(env)) + goto destroy; + + (*jvm)->DestroyJavaVM(jvm); + return (E_PO_SUCCESS); + +destroy: + if (lflag && explain_ex && (*env)->ExceptionOccurred(env)) + (*env)->ExceptionDescribe(env); + (*jvm)->DestroyJavaVM(jvm); + pu_die(err_desc); +} diff --git a/usr/src/cmd/pools/poold/poold.properties b/usr/src/cmd/pools/poold/poold.properties new file mode 100644 index 0000000000..2e56ce9d4a --- /dev/null +++ b/usr/src/cmd/pools/poold/poold.properties @@ -0,0 +1,47 @@ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 +# +#ident "%Z%%M% %I% %E% SMI" +# +# NOTICE: This file contains default settings for poold(1M). Do not +# edit this file. Its format and contents are subject to change in +# future releases of Solaris. + +# Objective Classes + +system.objectives= com.sun.solaris.domain.pools.WeightedLoadObjective +pset.objectives= com.sun.solaris.domain.pools.LocalityObjective, com.sun.solaris.domain.pools.UtilizationObjective + +# poold-specific logging properties (replacing default logging.properties) +.level= ALL + +# Set defaults for all logfiles (poold and API-generated) which are suitable +# for management by logadm(1M). +java.util.logging.FileHandler.limit = 0 +java.util.logging.FileHandler.count = 1 +java.util.logging.FileHandler.append = true + +# Change defaults for API-generated logfiles. +java.util.logging.FileHandler.pattern = /var/log/pool/java%u.log +java.util.logging.FileHandler.formatter = com.sun.solaris.service.logging.SysloglikeFormatter diff --git a/usr/src/cmd/pools/poolstat/Makefile b/usr/src/cmd/pools/poolstat/Makefile new file mode 100644 index 0000000000..f45f974697 --- /dev/null +++ b/usr/src/cmd/pools/poolstat/Makefile @@ -0,0 +1,65 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (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 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# cmd/pools/poolstat/Makefile + +PROG = poolstat +OBJS = poolstat.o poolstat_utils.o sa_libpool.o sa_kstat.o +SRCS = $(OBJS:%.o=%.c) $(COMMON_SRCS) +POFILES = $(OBJS:.o=.po) + +include ../../Makefile.cmd +include ../Makefile.pools + +CFLAGS += -I$(POOLSCOMMONDIR) $(EXTRA_CFLAGS) +sparc_COPTFLAG= +LDLIBS += -lpool -lkstat +XGETFLAGS = -a +CLOBBERFILES += $(POFILES) + +lint := LINTFLAGS += -I$(POOLSCOMMONDIR) + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) $(COMMON_OBJS) + $(LINK.c) -o $@ $(OBJS) $(COMMON_OBJS) $(LDLIBS) + $(POST_PROCESS) + +%.o : $(POOLSCOMMONDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +install: all $(ROOTPROG) + +clean: + $(RM) $(OBJS) $(COMMON_OBJS) $(POFILES) + +lint: lint_SRCS + +include ../../Makefile.targ diff --git a/usr/src/cmd/pools/poolstat/poolstat.c b/usr/src/cmd/pools/poolstat/poolstat.c new file mode 100644 index 0000000000..abea3e2e83 --- /dev/null +++ b/usr/src/cmd/pools/poolstat/poolstat.c @@ -0,0 +1,1009 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * poolstat - report active pool statistics + */ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <unistd.h> +#include <locale.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <errno.h> + +#include <pool.h> +#include "utils.h" +#include "poolstat.h" +#include "poolstat_utils.h" + +#ifndef TEXT_DOMAIN +#define TEXT_DOMAIN "SYS_TEST" +#endif + +/* calculate offset of a particular element in a structure */ +#define offsetof(s, m) ((size_t)(&(((s *)0)->m))) +#define addrof(s) ((char **)&(s)) + +/* verify if a field is printable in respect of the current option flags */ +#define PRINTABLE(i) ((lf->plf_ffs[(i)].pff_prt & D_FIELD) || \ + (lf->plf_ffs[(i)].pff_prt & X_FIELD)) + +typedef int (* formatter) (char *, int, int, poolstat_field_format_t *, char *); + +/* available field formatters */ +static int default_f(char *, int, int, poolstat_field_format_t *, char *); +static int bigno_f(char *, int, int, poolstat_field_format_t *, char *); +static int used_stat_f(char *, int, int, poolstat_field_format_t *, char *); +static int header_f(char *, int, int, poolstat_field_format_t *, char *); + +/* statistics bags used to collect data from various provider */ +static statistic_bag_t pool_sbag_s; +static statistic_bag_t pset_sbag_s; +static statistic_bag_t *pool_sbag = &pool_sbag_s; +static statistic_bag_t *pset_sbag = &pset_sbag_s; + +/* formatter objects for pset, defined in a default printing sequence */ +static poolstat_field_format_t pset_ffs[] = { + /* prt flags,name,header,type,width,minwidth,offset,formatter */ + { DX_FIELD, "id", "id", LL, 3, 1, addrof(pool_sbag), + offsetof(statistic_bag_t, sb_sysid), + (formatter)default_f }, + { DX_FIELD, "pool", "pool", STR, 20, 14, addrof(pool_sbag), + offsetof(statistic_bag_t, sb_name), + (formatter)default_f }, + { DX_FIELD, "type", "type", STR, 4, 5, addrof(pset_sbag), + offsetof(statistic_bag_t, sb_type), + (formatter)default_f }, + { D_FIELD, "rid", "rid", LL, 3, 1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_sysid), + (formatter)default_f }, + { DX_FIELD, "rset", "rset", STR, 20, 14, addrof(pset_sbag), + offsetof(statistic_bag_t, sb_name), + (formatter)default_f }, + { DX_FIELD, "min", "min", ULL, 4, 1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_min), + (formatter)bigno_f }, + { DX_FIELD, "max", "max", ULL, 4, 1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_max), + (formatter)bigno_f }, + { DX_FIELD, "size", "size", ULL, 4, 1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_size), + (formatter)default_f }, + { DX_FIELD, "used", "used", FL, 4, -1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_used), + (formatter)used_stat_f }, + { DX_FIELD, "load", "load", FL, 4, -1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_load), + (formatter)default_f } +}; + +/* formatter objects for pool, defined in a default printing sequence */ +static poolstat_field_format_t pool_ffs[] = { + /* prt flags,name,header,type,width,minwidth,offset,formatter */ + { D_FIELD, "id", "id", LL, 3, 1, addrof(pool_sbag), + offsetof(statistic_bag_t, sb_sysid), + (formatter)default_f }, + { D_FIELD, "pool", "pool", STR, 20, 13, addrof(pool_sbag), + offsetof(statistic_bag_t, sb_name), + (formatter)default_f }, + { D_FIELD, "p_size", "size", ULL, 4, 1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_size), + (formatter)default_f }, + { D_FIELD, "p_used", "used", FL, 4, -1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_used), + (formatter)default_f }, + { D_FIELD, "p_load", "load", FL, 4, -1, addrof(pset_sbag_s.bag), + offsetof(pset_statistic_bag_t, pset_sb_load), + (formatter)default_f }, +}; + +/* lists with formatter objects, one for each statistics field */ +static poolstat_line_format_t pool_lf; /* formatting list in default mode */ +static poolstat_line_format_t pset_lf; /* formatting list for psets */ + +/* name of pools to be shown */ +static poolstat_list_element_t *pnames; +/* + * type of resources to be shown, currently we only have one type 'pset' + * but, poolstat can be extended to handle new upcoming resource types. + */ +static poolstat_list_element_t *rtypes; + +/* a handle to the pool configuration */ +static pool_conf_t *conf; + +/* option flags */ +static int rflag; +static int pflag; +static int oflag; + +/* operands */ +static int interval = 0; /* update interval */ +static long count = 1; /* one run */ + +/* data structure handlers */ +static poolstat_list_element_t * + create_prt_sequence_list(char *, poolstat_line_format_t *); +static poolstat_list_element_t * + create_args_list(char *, poolstat_list_element_t *, const char *); + +/* statistics update function */ +static void sa_update(statistic_bag_t *, int); + +/* statistics printing function */ +static void prt_pool_stats(poolstat_list_element_t *); + +static void +usage(void) +{ + (void) fprintf(stderr, gettext( +"Usage:\n" +"poolstat [-p pool-list] [-r rset-list] [interval [count]]\n" +"poolstat [-p pool-list] [-o format -r rset-list] [interval [count]]\n" +" \'pool-list\' is a space-separated list of pool IDs or names\n" +" \'rset-list\' is \'all\' or \'pset\'\n" +" \'format\' for all resource types is one or more of:\n" +"\tid pool type rid rset min max size used load\n")); + (void) exit(E_USAGE); +} + +static int +Atoi(char *p, int *errp) +{ + int i; + char *q; + errno = 0; + i = strtol(p, &q, 10); + if (errno != 0 || q == p || *q != '\0') + *errp = -1; + else + *errp = 0; + return (i); +} + +int +main(int argc, char *argv[]) +{ + char c; + int error = 0; + + (void) getpname(argv[0]); + (void) setlocale(LC_ALL, ""); + (void) textdomain(TEXT_DOMAIN); + + /* pset_sbag_s is used to collect pset statistics */ + pset_sbag_s.sb_type = PSET_TYPE_NAME; + pset_sbag_s.bag = ZALLOC(sizeof (pset_statistic_bag_t)); + pool_sbag_s.sb_type = POOL_TYPE_NAME; + + pset_lf.plf_ffs = pset_ffs; + pset_lf.plf_ff_len = sizeof (pset_ffs) / + sizeof (poolstat_field_format_t); + pool_lf.plf_ffs = pool_ffs; + pool_lf.plf_ff_len = sizeof (pool_ffs) / + sizeof (poolstat_field_format_t); + + while ((c = getopt(argc, argv, ":p:r:o:")) != EOF) { + switch (c) { + case 'p': /* pool name specification */ + pflag++; + pnames = create_args_list(optarg, pnames, + " \t"); + break; + case 'r': { /* resource type */ + rflag++; + rtypes = create_args_list(optarg, rtypes, + " \t,"); + break; + } + case 'o': { /* format specification */ + oflag++; + if (create_prt_sequence_list(optarg, &pset_lf) == NULL) + usage(); + break; + } + case ':': { + (void) fprintf(stderr, + gettext(ERR_OPTION_ARGS), optopt); + usage(); + /*NOTREACHED*/ + } + default: + (void) fprintf(stderr, gettext(ERR_OPTION), optopt); + usage(); + /*NOTREACHED*/ + } + } + + /* get operands */ + if (argc > optind) { + if ((interval = Atoi(argv[optind++], &error)) < 1 || error != 0) + usage(); + count = -1; + } + if (argc > optind) { + if ((count = Atoi(argv[optind++], &error)) < 1 || error != 0) + usage(); + } + /* check for extra options/operands */ + if (argc > optind) + usage(); + + /* check options */ + if (oflag && !rflag) + usage(); + + /* global initializations */ + if (!oflag) { + /* create the default print sequences */ + (void) create_prt_sequence_list(NULL, &pool_lf); + (void) create_prt_sequence_list(NULL, &pset_lf); + } + + if (rtypes == NULL || strcmp(rtypes->ple_obj, "all") == 0) { + /* crate a default resource list */ + FREE(rtypes); + rtypes = create_args_list("pset", NULL, " \t,"); + } + + if ((conf = pool_conf_alloc()) == NULL) + die(gettext(ERR_NOMEM)); + if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY) + != PO_SUCCESS) + die(gettext(ERR_OPEN_DYNAMIC), get_errstr()); + + /* initialize statistic adapters */ + sa_libpool_init(conf); + sa_kstat_init(NULL); + + /* collect and print out statistics */ + while (count-- != 0) { + sa_update(pool_sbag, SA_REFRESH); + if (pool_sbag->sb_changed & POU_POOL) + (void) printf( + "<<State change>>\n"); + prt_pool_stats(pnames); + if (count != 0) { + (void) sleep(interval); + if (rflag) + (void) printf("\n"); + } + } + + return (E_PO_SUCCESS); +} + +/* + * Take the arguments and create/append a string list to the 'le' list. + */ +static poolstat_list_element_t * +create_args_list(char *arg, poolstat_list_element_t *le, const char *delim) +{ + poolstat_list_element_t *head = le; + + while (arg != NULL && *arg != '\0') { + char *name = arg; + arg = strpbrk(arg, delim); + if (arg != NULL) { + *arg++ = '\0'; + } + if (le == NULL) { + /* create first element */ + NEW0(le); + head = le; + } else { + /* find last and append */ + while (le->ple_next != NULL) + le = le->ple_next; + NEW0(le->ple_next); + le = le->ple_next; + } + le->ple_obj = (void *)name; + } + + return (head); +} + +/* + * Take the arguments to the -o option, and create a format field list in order + * specified by 'arg'. + * If 'arg' is NULL a list in a default printing order is created. + */ +static poolstat_list_element_t * +create_prt_sequence_list(char *arg, poolstat_line_format_t *lf) +{ + /* + * Create a default print sequence. It is the sequence defined + * statically in the format list. At the same time mark the fields + * printable according to the current option settings. + */ + if (arg == NULL) { + int i; + NEW0(lf->plf_prt_seq); + lf->plf_ffs[0].pff_prt |= PRINTABLE(0) ? PABLE_FIELD : 0; + lf->plf_last = lf->plf_prt_seq; + lf->plf_last->ple_obj = &(lf->plf_ffs[0]); + for (i = 1; i < lf->plf_ff_len; i++) { + lf->plf_ffs[i].pff_prt |= + PRINTABLE(i) ? PABLE_FIELD : 0; + NEW0(lf->plf_last->ple_next); + lf->plf_last = lf->plf_last->ple_next; + lf->plf_last->ple_obj = &(lf->plf_ffs[i]); + } + return (lf->plf_prt_seq); + } + + while (arg != NULL && *arg != '\0') { + poolstat_field_format_t *ff; /* current format field */ + int ffIdx; /* format field index */ + char *name; /* name of field */ + int n; /* no. of chars to strip */ + + n = strspn(arg, " ,\t\r\v\f\n"); + arg += n; /* strip multiples separator */ + name = arg; + + if (strlen(name) < 1) + break; + + if ((arg = strpbrk(arg, " ,\t\r\v\f\n")) != NULL) + *arg++ = '\0'; + + /* search for a named format field */ + for (ffIdx = 0; ffIdx < lf->plf_ff_len; ffIdx++) { + ff = lf->plf_ffs + ffIdx; + if (strcmp(ff->pff_name, name) == 0) { + ff->pff_prt |= PABLE_FIELD; + break; + } + } + /* if the name wasn't found */ + if (ffIdx == lf->plf_ff_len) { + (void) fprintf(stderr, gettext(ERR_UNSUPP_STAT_FIELD), + name); + usage(); + } + if (lf->plf_last == NULL) { + /* create first print handle */ + NEW0(lf->plf_prt_seq); + lf->plf_last = lf->plf_prt_seq; + } else { + NEW0(lf->plf_last->ple_next); + lf->plf_last = lf->plf_last->ple_next; + } + lf->plf_last->ple_obj = ff; /* refer to the format field */ + } + + return (lf->plf_prt_seq); +} + +/* update the statistic data by adapters */ +static void +sa_update(statistic_bag_t *sbag, int flags) +{ + sa_libpool_update(sbag, flags); + sa_kstat_update(sbag, flags); +} + +/* + * Format one statistic field and put it into the 'str' buffer. 'ff' contains + * the field formatting parameters. Return the number of used bytes. + */ +static int +default_f(char *str, int pos, int left, poolstat_field_format_t *ff, char *data) +{ + int used; + + switch (ff->pff_type) { + case LL: { + int64_t v; + v = *((int64_t *)(void *)(data + ff->pff_offset)); + used = snprintf(str + pos, left, "%*.*lld", + ff->pff_width, ff->pff_minwidth, v); + } + break; + case ULL: { + uint64_t v; + v = *((uint64_t *)(void *)(data + ff->pff_offset)); + used = snprintf(str + pos, left, "%*.*llu", + ff->pff_width, ff->pff_minwidth, v); + }; + break; + case FL: { + int pw = 0; + double v = *((double *)(void *)(data + ff->pff_offset)); + if (v < 10) { + pw = ff->pff_width - 2; + } else if (v < 100) { + pw = ff->pff_width - 3; + } else if (v < 1000) { + pw = ff->pff_width - 4; + } + if (pw < 0) + pw = 0; + used = snprintf(str + pos, left, "%*.*f", + ff->pff_width, pw, v); + }; + break; + case STR: { + char *v; + int sl; + v = *((char **)(void *)(data + ff->pff_offset)); + sl = strlen(v); + /* truncate if it doesn't fit */ + if (sl > ff->pff_width) { + char *cp = v + ff->pff_width - 1; + if (ff->pff_width < 4) + die(gettext(ERR_STATS_FORMAT), + ff->pff_header); + *cp-- = 0; + *cp-- = '.'; + *cp-- = '.'; + *cp-- = '.'; + } + used = snprintf(str + pos, left, "%-*s", ff->pff_width, + v); + } + break; + } + + return (used); +} + +/* format big numbers */ +static int +bigno_f(char *str, int pos, int left, poolstat_field_format_t *ff, char *data) +{ + uint64_t v; + char tag; + int pw = ff->pff_width - 4; + double pv; + int used; + + v = *((uint64_t *)(void *)(data + ff->pff_offset)); + /* + * the max value can be ULONG_MAX, which is formatted as: + * E P T G M K + * 18 446 744 073 709 551 615 + * As a result ULONG_MAX is displayed as 18E + */ + pv = v; + if (v < 1000) { + pw = 0; + } else if (v < KILO * 10) { + pv = (double)v / KILO; + tag = 'K'; + } else if (v < KILO * 100) { + pv = (double)v / KILO; + tag = 'K'; pw -= 1; + } else if (v < KILO * 1000) { + pv = (double)v / KILO; + tag = 'K'; pw -= 2; + } else if (v < MEGA * 10) { + pv = (double)v / MEGA; + tag = 'M'; + } else if (v < MEGA * 100) { + pv = (double)v / MEGA; + tag = 'M'; pw -= 1; + } else if (v < MEGA * 1000) { + pv = (double)v / MEGA; + tag = 'M'; pw -= 2; + } else if (v < GIGA * 10) { + pv = (double)v / GIGA; + tag = 'G'; + } else if (v < GIGA * 100) { + pv = (double)v / GIGA; + tag = 'G'; pw -= 1; + } else if (v < GIGA * 1000) { + pv = (double)v / GIGA; + tag = 'G'; pw -= 2; + } else if (v < TERA * 10) { + pv = (double)v / TERA; + tag = 'T'; + } else if (v < TERA * 100) { + pv = (double)v / TERA; + tag = 'T'; pw -= 1; + } else if (v < TERA * 1000) { + pv = (double)v / TERA; + tag = 'T'; pw -= 2; + } else if (v < PETA * 10) { + pv = (double)v / PETA; + tag = 'P'; + } else if (v < PETA * 100) { + pv = (double)v / PETA; + tag = 'P'; pw -= 1; + } else if (v < PETA * 1000) { + pv = (double)v / PETA; + tag = 'P'; pw -= 2; + } else if (v < EXA * 10) { + pv = (double)v / EXA; + tag = 'E'; + } else if (v < EXA * 100) { + pv = (double)v / EXA; + tag = 'E'; pw -= 1; + } else { + pv = (double)v / EXA; + tag = 'E'; pw -= 2; + } + if (pw < 0) + pw = 0; + if (v < 1000) + used = snprintf(str + pos, left, "%*.*f", + ff->pff_width, pw, pv); + else + used = snprintf(str + pos, left, "%*.*f%c", + ff->pff_width - 1, pw, pv, tag); + + return (used); +} + +/* format usage statistic, if configuration has changed print '-'. */ +static int +used_stat_f(char *str, int pos, int left, poolstat_field_format_t *ff, + char *data) +{ + int pw = 0; + double v = *((double *)(void *)(data + ff->pff_offset)); + int used; + + if (pool_sbag->sb_changed & POU_POOL) { + used = snprintf(str + pos, left, "%*c", ff->pff_width, '-'); + } else { + if (v < 10) { + pw = ff->pff_width - 2; + } else if (v < 100) { + pw = ff->pff_width - 3; + } else if (v < 1000) { + pw = ff->pff_width - 4; + } + if (pw < 0) + pw = 0; + used = snprintf(str + pos, left, "%*.*f", + ff->pff_width, pw, v); + } + return (used); +} + +/* + * Format one header field and put it into the 'str' buffer. + */ +/*ARGSUSED*/ +static int +header_f(char *str, int pos, int left, poolstat_field_format_t *ff, char *data) +{ + int used = 0; + + if (ff->pff_type == STR) + /* strings are left justified */ + used = snprintf(str + pos, left, "%-*s", + ff->pff_width, ff->pff_header); + else + used = snprintf(str + pos, left, "%*s", + ff->pff_width, ff->pff_header); + return (used); +} + +/* + * Print one statistic line according to the definitions in 'lf'. + */ +static void +prt_stat_line(poolstat_line_format_t *lf) +{ + poolstat_list_element_t *le; /* list element in the print sequence */ + char *line; + int pos = 0; /* position in the printed line */ + int len = MAXLINE; /* the length of the line */ + int left = len; /* chars left to use in the line */ + + line = ZALLOC(len); + for (le = lf->plf_prt_seq; le; le = le->ple_next) { + int used; + poolstat_field_format_t *ff = + (poolstat_field_format_t *)le->ple_obj; + /* if the filed is marked to be printed */ + if (ff->pff_prt & PABLE_FIELD) { + if (((used = ff->pff_format(line, pos, left, ff, + *ff->pff_data_ptr)) + 1) >= left) { + /* if field doesn't fit allocate new space */ + len += used + MAXLINE; + left += used + MAXLINE; + line = REALLOC(line, len); + if (((used = ff->pff_format(line, pos, left, ff, + *ff->pff_data_ptr)) + 1) >= left) + die(gettext(ERR_STATS_FORMAT), line); + } + left -= used; + pos += used; + if (le->ple_next != NULL) { + /* separate columns with a space */ + line[pos++] = ' '; + left--; + } + } + } + + (void) printf("%s\n", line); + FREE(line); +} + +/* + * Print a statistics header line for a given resource type. + */ +static void +prt_stat_hd(const char *type) +{ + poolstat_line_format_t *lf; /* line format */ + poolstat_list_element_t *le; /* list element in the print sequence */ + char *line; + int pos = 0; /* position in the printed line */ + int len = MAXLINE; /* the length of the line */ + int left = len; /* chars left to use in the line */ + + if (strcmp(type, POOL_TYPE_NAME) == 0) { + /* pool format needs an extra header */ + (void) printf("%*s\n", 19 + 15, "pset"); + lf = &pool_lf; + } else if (strcmp(type, PSET_TYPE_NAME) == 0) { + lf = &pset_lf; + } else { + die(gettext(ERR_UNSUPP_RTYPE), type); + } + line = ZALLOC(len); + for (le = lf->plf_prt_seq; le; le = le->ple_next) { + int used; /* used chars in line */ + poolstat_field_format_t *ff = + (poolstat_field_format_t *)le->ple_obj; + /* if the filed is marked to be printed */ + if (ff->pff_prt& PABLE_FIELD) { + if (((used = header_f(line, pos, left, ff, NULL)) + 1) + >= left) { + /* if field doesn't fit allocate new space */ + len += used + MAXLINE; + left += used + MAXLINE; + line = REALLOC(line, len); + if (((used = header_f(line, pos, left, ff, + NULL)) + 1) >= left) + die(gettext(ERR_STATS_FORMAT), line); + } + left -= used; + pos += used; + if (le->ple_next != NULL) { + /* separate columns with a space */ + line[pos++] = ' '; + left--; + } + } + } + + /* only header line with non space characters should be printed */ + pos = 0; + while (*(line + pos) != '\n') { + if (!isspace(*(line + pos))) { + (void) printf("%s\n", line); + + break; + } + pos++; + } + FREE(line); +} + +/* + * Create a pool value instance and set its name to 'name'. + */ +static pool_value_t * +create_pool_value(const char *name) +{ + pool_value_t *pval; + + if ((pval = pool_value_alloc()) == NULL) { + return (NULL); + } + if (pool_value_set_name(pval, name) != PO_SUCCESS) { + pool_value_free(pval); + return (NULL); + } + + return (pval); +} + +/* + * Find all resources of type 'rtype'. + * If 'pool_name' is defined find all resources bound to this pool. + */ +static pool_resource_t ** +get_resources(const char *pool_name, const char *rtype, uint_t *nelem) +{ + pool_resource_t **resources = NULL; + pool_value_t *pvals[] = { NULL, NULL, NULL}; + pool_value_t *pv_sys_id; + pool_value_t *pv_name; + char *name_prop; /* set name property */ + + if (strcmp(rtype, PSET_TYPE_NAME) == 0) { + if ((pv_sys_id = create_pool_value(PSET_SYSID)) == NULL) + goto on_error; + name_prop = PSET_NAME; + } else { + die(gettext(ERR_UNSUPP_RTYPE), rtype); + } + + if ((pvals[0] = create_pool_value("type")) == NULL) + goto on_error; + if ((pool_value_set_string(pvals[0], rtype)) == -1) + goto on_error; + + if ((pv_name = create_pool_value(name_prop)) == NULL) + goto on_error; + + if (pool_name != NULL) { + /* collect resources associated to 'pool_name' */ + pool_t *pool; + if ((pool = pool_get_pool(conf, pool_name)) == NULL) + die(gettext(ERR_STATS_POOL_N), pool_name); + if ((resources = pool_query_pool_resources( + conf, pool, nelem, pvals)) == NULL) + goto on_error; + } else { + /* collect all resources */ + if ((resources = + pool_query_resources(conf, nelem, pvals)) == NULL) + goto on_error; + } + + if (pv_name != NULL) + pool_value_free(pv_name); + if (pv_sys_id != NULL) + pool_value_free(pv_sys_id); + if (pvals[0] != NULL) + pool_value_free(pvals[0]); + + return (resources); +on_error: + die(gettext(ERR_STATS_RES), get_errstr()); + /*NOTREACHED*/ +} + +/* + * Print statistics for all resources of type 'rtype' passed in 'resources'. + */ +static void +prt_resource_stats_by_type(pool_resource_t **resources, const char *rtype) +{ + int i; + pool_elem_t *elem; + pool_value_t *pv_name; + char *name_prop; + + poolstat_line_format_t *lf; + statistic_bag_t *sbag; + + if (strcmp(rtype, PSET_TYPE_NAME) == 0) { + name_prop = PSET_NAME; + lf = &pset_lf; + sbag = pset_sbag; + } else { + die(gettext(ERR_UNSUPP_RTYPE), rtype); + } + + if ((pv_name = create_pool_value(name_prop)) == NULL) + goto on_error; + + /* collect and print statistics for the given resources */ + for (i = 0; resources[i] != NULL; i++) { + if ((elem = pool_resource_to_elem(conf, resources[i])) == NULL) + goto on_error; + if (pool_get_property(conf, elem, name_prop, pv_name) == -1) + goto on_error; + if (pool_value_get_string(pv_name, &sbag->sb_name) == -1) + goto on_error; + sa_update(sbag, 0); + + prt_stat_line(lf); + } + + if (pv_name != NULL) + pool_value_free(pv_name); + return; +on_error: + die(gettext(ERR_STATS_RES), get_errstr()); +} + +/* + * Update statistics for all resources of type 'rtype' pased in 'resources'. + */ +static void +update_resource_stats(pool_resource_t *resource, const char *rtype) +{ + pool_elem_t *elem; + pool_value_t *pv_name; + char *name_prop; /* set name property */ + + statistic_bag_t *sbag; + + if (strcmp(rtype, PSET_TYPE_NAME) == 0) { + name_prop = PSET_NAME; + sbag = pset_sbag; + } else { + die(gettext(ERR_UNSUPP_RTYPE), rtype); + } + + if ((pv_name = create_pool_value(name_prop)) == NULL) + goto on_error; + + if ((elem = pool_resource_to_elem(conf, resource)) == NULL) + goto on_error; + if (pool_get_property(conf, elem, name_prop, pv_name) == -1) + goto on_error; + if (pool_value_get_string(pv_name, &sbag->sb_name) == -1) + goto on_error; + sa_update(sbag, 0); + + if (pv_name != NULL) + pool_value_free(pv_name); + return; + +on_error: + die(gettext(ERR_STATS_RES), get_errstr()); +} + +/* + * For each pool in the configuration print statistics of associated resources. + * If the pool name list 'pn' is defined, only print resources of pools + * specified in the list. The list can specify the pool name or its system id. + */ +static void +prt_pool_stats(poolstat_list_element_t *pn) +{ + uint_t nelem; + pool_elem_t *elem; + int i; + int error; + pool_t **pools = NULL; + pool_value_t *pvals[] = { NULL, NULL }; + pool_value_t *pv_name = NULL; + pool_value_t *pv_sys_id = NULL; + statistic_bag_t *sbag = pool_sbag; + poolstat_list_element_t *rtype; + pool_resource_t **resources; + + if ((pv_sys_id = create_pool_value(POOL_SYSID)) == NULL) + goto on_error; + if ((pv_name = create_pool_value(POOL_NAME)) == NULL) + goto on_error; + + if (pn == NULL) { + /* collect all pools */ + if ((pools = pool_query_pools(conf, &nelem, NULL)) == NULL) + goto on_error; + } else { + /* + * collect pools specified in the 'pn' list. + * 'poolid' the pool identifier can be a pool name or sys_id. + */ + poolstat_list_element_t *poolid; + for (poolid = pn, i = 1; poolid; poolid = poolid->ple_next) + i++; + pools = ZALLOC(sizeof (pool_t *) * (i + 1)); + for (poolid = pn, i = 0; poolid; + poolid = poolid->ple_next, i++) { + pool_t **pool; + int64_t sysid = Atoi(poolid->ple_obj, &error); + if (error == 0) { + /* the pool is identified by sys_id */ + pool_value_set_int64(pv_sys_id, sysid); + pvals[0] = pv_sys_id; + pool = pool_query_pools(conf, &nelem, pvals); + } else { + if (pool_value_set_string(pv_name, + poolid->ple_obj) == -1) + die(gettext(ERR_NOMEM)); + pvals[0] = pv_name; + pool = pool_query_pools(conf, &nelem, pvals); + } + if (pool == NULL) + die(gettext(ERR_STATS_POOL_N), poolid->ple_obj); + pools[i] = pool[0]; + FREE(pool); + } + } + + /* print statistic for all pools found */ + if (!rflag) { + /* print the common resource header */ + prt_stat_hd(POOL_TYPE_NAME); + + /* print statistics for the resources bound to the pools */ + for (i = 0; pools[i] != NULL; i++) { + elem = pool_to_elem(conf, pools[i]); + if (pool_get_property(conf, elem, POOL_NAME, pv_name) + == -1) + goto on_error; + if (pool_value_get_string(pv_name, &sbag->sb_name) != 0) + goto on_error; + if (pool_get_property( + conf, elem, "pool.sys_id", pv_sys_id) == -1) + goto on_error; + if (pool_value_get_int64( + pv_sys_id, &sbag->sb_sysid) != 0) + goto on_error; + + for (rtype = rtypes; rtype; rtype = rtype->ple_next) { + resources = get_resources( + sbag->sb_name, rtype->ple_obj, &nelem); + update_resource_stats(*resources, + rtype->ple_obj); + FREE(resources); + } + prt_stat_line(&pool_lf); + } + } else { + /* print statistic for all resource types defined in rtypes */ + for (rtype = rtypes; rtype; rtype = rtype->ple_next) { + prt_stat_hd(rtype->ple_obj); + for (i = 0; pools[i] != NULL; i++) { + elem = pool_to_elem(conf, pools[i]); + if (pool_get_property( + conf, elem, POOL_NAME, pv_name) == -1) + goto on_error; + if (pool_value_get_string( + pv_name, &sbag->sb_name) != 0) + goto on_error; + if (pool_get_property( + conf, elem, POOL_SYSID, pv_sys_id) + == -1) + goto on_error; + if (pool_value_get_int64( + pv_sys_id, &sbag->sb_sysid) != 0) + goto on_error; + resources = get_resources( + sbag->sb_name, rtype->ple_obj, &nelem); + if (resources == NULL) + continue; + update_resource_stats( + *resources, rtype->ple_obj); + prt_resource_stats_by_type(resources, + rtype->ple_obj); + FREE(resources); + } + } + } + + FREE(pools); + if (pv_name != NULL) + pool_value_free(pv_name); + if (pv_sys_id != NULL) + pool_value_free(pv_sys_id); + + return; +on_error: + die(gettext(ERR_STATS_POOL), get_errstr()); +} diff --git a/usr/src/cmd/pools/poolstat/poolstat.h b/usr/src/cmd/pools/poolstat/poolstat.h new file mode 100644 index 0000000000..ba5204c33d --- /dev/null +++ b/usr/src/cmd/pools/poolstat/poolstat.h @@ -0,0 +1,190 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _POOLSTAT_H +#define _POOLSTAT_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The following are types and defines used to collect statistic data. + * Different statistic providers can be used to collect the data. + * Two functions build the interface to each provider: + * 'provider'_init(), and 'provider'_update(). In the update function + * a provider fills out the passed data structure with statistics data + * it is responsible for. + */ + +/* Error messages for poolstat */ +#define ERR_LOAD_AVERAGE "cannot get load average: %s\n" +#define ERR_BINDING "cannot get resource binding: %s\n" +#define ERR_STATS_POOL_N "cannot get statistics for pool '%s'\n" +#define ERR_STATS_RES_N "cannot get statistics for resource '%s': %s\n" +#define ERR_STATS_POOL "cannot get pool statistics: %s\n" +#define ERR_STATS_RES "cannot get resource statistics: %s\n" +#define ERR_STATS_FORMAT "cannot format statistic line: %s\n" +#define ERR_KSTAT_OPEN "kstat open failed: %s\n" +#define ERR_KSTAT_DATA "cannot get kstat data: %s\n" +#define ERR_KSTAT_DLOOKUP "kstat_data_lookup('%s', '%s') failed: %s\n" +#define ERR_OPTION_ARGS "Option -%c requires an argument\n" +#define ERR_OPTION "poolstat: illegal option -- %c\n" +#define ERR_CONF_UPDATE "pool configuration update failed: %s\n" +#define ERR_UNSUPP_STYPE "unsupported statistic type: %s\n" +#define ERR_UNSUPP_RTYPE "unsupported resource type: %s\n" +#define ERR_UNSUPP_STAT_FIELD "unsupported statistic field: %s\n" + +#define POOL_TYPE_NAME "pool" +#define PSET_TYPE_NAME "pset" +#define POOL_SYSID "pool.sys_id" +#define PSET_SYSID "pset.sys_id" + +/* set types */ +typedef enum { ST_PSET } st_t; + +/* update flag, forces refresh of statistic data */ +#define SA_REFRESH 1 + +/* data bag used to collect statistics for a processor set */ +typedef struct { + int64_t pset_sb_sysid; + uint64_t pset_sb_min; + uint64_t pset_sb_max; + uint64_t pset_sb_size; + double pset_sb_used; + double pset_sb_load; + uint64_t pset_sb_changed; +} pset_statistic_bag_t; + +/* wrapper for different statistic bags */ +typedef struct { + const char *sb_name; /* pool or resource name used as identifier */ + int64_t sb_sysid; /* the sysid */ + const char *sb_type; /* the type can be "pool", or "pset" */ + uint64_t sb_changed; + void* bag; +} statistic_bag_t; + +/* shortcut to access a element in the pset statistic bag. */ +#define PSETBAG_ELEM(p, e) (((pset_statistic_bag_t *)(p)->bag)->e) + +/* statistic adapters */ +extern void sa_libpool_init(void *); +extern void sa_libpool_update(statistic_bag_t *sbag, int flags); +extern void sa_kstat_init(void *); +extern void sa_kstat_update(statistic_bag_t *sbag, int flags); + +/* + * The following types and defines are used to format statistic lines. + * All formatting information for a particular line are grouped in 'lf_t' + * structure. + * Two data sequences are anchored there: an array with all possible formatting + * directives for fields that can occur in a statistic line, and a list with + * pointers to elements in this array. This list defines which fields and in + * which order should be printed. + * Formatting directives for one field are grouped in 'poolstat_field_format_t' + * structure. Basically it contains a pointer to a formatting function and some + * formatting parameters used by this function. + */ + +/* the length of a statistic line */ +#define MAXLINE 160 +/* default print field */ +#define D_FIELD 0x01 +/* -x option print field */ +#define X_FIELD 0x02 +/* -o option print field */ +#define O_FIELD 0x04 + +/* print field in default and extended mode */ +#define DX_FIELD (D_FIELD | X_FIELD) + +/* marks a field as printable */ +#define PABLE_FIELD 0x80 + +#define KILO 1000 +#define MEGA ((uint64_t)(KILO * 1000)) +#define GIGA ((uint64_t)(MEGA * 1000)) +#define TERA ((uint64_t)(GIGA * 1000)) +#define PETA ((uint64_t)(TERA * 1000)) +#define EXA ((uint64_t)(PETA * 1000)) + +#define KBYTE 1024 +#define MBYTE ((uint64_t)(KBYTE * 1024)) +#define GBYTE ((uint64_t)(MBYTE * 1024)) +#define TBYTE ((uint64_t)(GBYTE * 1024)) +#define PBYTE ((uint64_t)(TBYTE * 1024)) +#define EBYTE ((uint64_t)(PBYTE * 1024)) + +/* statistic data types */ +typedef enum { ULL, LL, FL, STR } dt_t; + +/* poolstat_field_format_t contains information for one statistic field */ +typedef struct poolstat_field_format { + int pff_prt; /* printable flag */ + const char *pff_name; /* name of the statistic */ + const char *pff_header; + const dt_t pff_type; /* the data type */ + int pff_width; /* width, excluding whitespace */ + const int pff_minwidth; + char **pff_data_ptr; + const size_t pff_offset; /* offset in a data block */ + /* formatter */ + int (* pff_format) + (char *, int, int, struct poolstat_field_format *, char *); +} poolstat_field_format_t; + +/* list element, used to link arbitrary objects in a list */ +typedef struct _myself { + void *ple_obj; + struct _myself *ple_next; +} poolstat_list_element_t; + +/* + * poolstat_line_format_t contains formatting information for one + * statistics line. + */ +typedef struct { + /* pointer to an array with all format fields */ + poolstat_field_format_t *plf_ffs; + /* the lenght of format field array */ + int plf_ff_len; + /* the field's print sequence */ + poolstat_list_element_t *plf_prt_seq; + /* pointer to the last field in prt. sequence */ + poolstat_list_element_t *plf_last; +} poolstat_line_format_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _POOLSTAT_H */ diff --git a/usr/src/cmd/pools/poolstat/poolstat_utils.c b/usr/src/cmd/pools/poolstat/poolstat_utils.c new file mode 100644 index 0000000000..28c1f44fce --- /dev/null +++ b/usr/src/cmd/pools/poolstat/poolstat_utils.c @@ -0,0 +1,51 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libintl.h> +#include <string.h> +#include <errno.h> +#include <poll.h> + +#include "utils.h" +#include "poolstat_utils.h" + +void * +Realloc(void *ptr, size_t nbytes) +{ + if ((ptr = realloc(ptr, nbytes))) + return (ptr); + + die(gettext(ERR_NOMEM)); + /*NOTREACHED*/ +} + +void * +Zalloc(size_t nbytes) +{ + return (memset(Realloc(NULL, nbytes), 0, nbytes)); +} diff --git a/usr/src/cmd/pools/poolstat/poolstat_utils.h b/usr/src/cmd/pools/poolstat/poolstat_utils.h new file mode 100644 index 0000000000..7beb2d5637 --- /dev/null +++ b/usr/src/cmd/pools/poolstat/poolstat_utils.h @@ -0,0 +1,52 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _POOLSTAT_UTILS_H +#define _POOLSTAT_UTILS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define REALLOC(p, nbytes) Realloc((p), (nbytes)) +#define ZALLOC(nbytes) Zalloc((nbytes)) + +#define FREE(p) ((void) (free((p)), (p) = 0)) +#define NEW0(p) ((p) = ZALLOC((long)sizeof (*(p)))) + +extern void *Zalloc(size_t); +extern void *Realloc(void *, size_t); +extern void Free(void *); + +#ifdef __cplusplus +} +#endif + +#endif /* _POOLSTAT_UTILS_H */ diff --git a/usr/src/cmd/pools/poolstat/sa_kstat.c b/usr/src/cmd/pools/poolstat/sa_kstat.c new file mode 100644 index 0000000000..465e38f1d1 --- /dev/null +++ b/usr/src/cmd/pools/poolstat/sa_kstat.c @@ -0,0 +1,346 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * sa_kstat - kstat statistic adapter, collects statistic data provided + * by kstat. + */ + +#include <locale.h> +#include <string.h> +#include <assert.h> +#include <kstat.h> +#include <pool.h> +#include "utils.h" +#include <sys/pset.h> +#include "poolstat.h" +#include "poolstat_utils.h" + +/* marks 'sdata_t' element as updated */ +#define SD_UPDATED 1 + +/* Specified value for an invalid set. */ +#define INVALID_SET -2 + +/* statistic data */ +typedef struct sdata { + kstat_t sd_oks; /* old kstat */ + kstat_t sd_nks; /* new kstat */ + void *sd_udata; /* user data */ + uint_t sd_state; /* state of this data (UPDATED) */ + struct sdata *sd_next; +} sdata_t; + +/* pset user data */ +typedef struct { + psetid_t opset; /* old pset sysid */ + psetid_t npset; /* new pset sysid */ +} pset_ud_t; + +/* shortcuts to access set's id in 'pset_ud_t' */ +#define SD_OPSET(p) (((pset_ud_t *)(p)->sd_udata)->opset) +#define SD_NPSET(p) (((pset_ud_t *)(p)->sd_udata)->npset) + +static kstat_ctl_t *ks_ctl; /* libkstat handle */ +static sdata_t *cpu_list; /* list with cpu statistics */ + +static sdata_t *update_sdata_list(sdata_t *, kstat_ctl_t *, char *, int, + char *, int *); +static void update_cpu_list(sdata_t *list); +static void update_pset_stats(statistic_bag_t *, sdata_t *); + +/*ARGSUSED*/ +void +sa_kstat_init(void *unused) +{ + if ((ks_ctl = kstat_open()) == NULL) + die(gettext(ERR_KSTAT_OPEN), get_errstr()); +} + +void +sa_kstat_update(statistic_bag_t *sbag, int flags) +{ + /* The SA_REFRESH flag forces the update of local data structures. */ + if (flags & SA_REFRESH) { + int ks_error = 0; + + if (kstat_chain_update(ks_ctl) == -1) + die(gettext(ERR_KSTAT_DATA), get_errstr()); + cpu_list = update_sdata_list(cpu_list, ks_ctl, "cpu", + -1, "sys", &ks_error); + if (ks_error) + die(gettext(ERR_KSTAT_DATA), get_errstr()); + + /* update info about cpu binding to processor sets */ + update_cpu_list(cpu_list); + } + + if (strcmp(sbag->sb_type, PSET_TYPE_NAME) == 0) { + update_pset_stats(sbag, cpu_list); + } else if (strcmp(sbag->sb_type, POOL_TYPE_NAME) == 0) { + return; + } else { + die(gettext(ERR_UNSUPP_STYPE), sbag->sb_type); + } + +} + +static void * +safe_kstat_data_lookup(kstat_t *ksp, char *name) +{ + void *dp; + + if ((dp = kstat_data_lookup(ksp, name)) == NULL) + die(gettext(ERR_KSTAT_DLOOKUP), + ksp->ks_name, name, get_errstr()); + + return (dp); +} + +/* + * Find the delta over the interval between new_ksp and old_ksp. + * If old_ksp->ks_data is NULL and 'oz' is set then pretend + * that old_ksp is zero otherwise return 0. + */ +static uint64_t +delta(kstat_t *new_ksp, kstat_t *old_ksp, char *name, int oz) +{ + kstat_named_t *new_ksn; + kstat_named_t *old_ksn; + + new_ksn = (kstat_named_t *)safe_kstat_data_lookup(new_ksp, name); + if (old_ksp == NULL || old_ksp->ks_data == NULL) + return ((oz == 1) ? new_ksn->value.ui64 : 0); + old_ksn = (kstat_named_t *)safe_kstat_data_lookup(old_ksp, name); + + return (new_ksn->value.ui64 - old_ksn->value.ui64); +} + +/* + * Create a clone of the passed kstat_t structure 'kstat_t'. If + * 'fr' flag is set free the old ks_data structure in 'dst'. + */ +static void +kstat_clone(kstat_t *src, kstat_t *dst, int fr) +{ + if (fr) + FREE(dst->ks_data); + *dst = *src; + if (src->ks_data != NULL) { + dst->ks_data = ZALLOC(src->ks_data_size); + (void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size); + } else { + dst->ks_data = NULL; + dst->ks_data_size = 0; + } +} + +/* + * Erase the data from 'src'. + */ +static void +kstat_erase(kstat_t *src) +{ + FREE(src->ks_data); + (void) memset(src, 0, sizeof (*src)); +} + +/* + * Create a new statistic data object with its own copy of the passed + * kstat. + */ +static sdata_t * +sdata_new(kstat_t *ksp) +{ + sdata_t *sdp; + + NEW0(sdp); + kstat_clone(ksp, &sdp->sd_nks, 0); + + return (sdp); +} + +static void +sdata_free(sdata_t *sdp) +{ + FREE(sdp->sd_oks.ks_data); + FREE(sdp->sd_nks.ks_data); + FREE(sdp->sd_udata); + FREE(sdp); +} + +/* + * Create new or update an existing list of cpu statistics. For each + * cpu two kstats are kept. One old kstat which contains the data from + * the previous scan, and new with the current data. The old and the new + * kstats *must* be for the same instance and have the same kid. + * If 'instance' argument is set to -1 don't use it as a filter. + */ +static sdata_t * +update_sdata_list(sdata_t *list, kstat_ctl_t *kc, char *module, + int instance, char *name, int *errp) +{ + kstat_t *ksp; + sdata_t *sdp, *sdpp; /* kstat instance pointer/previous-pointer */ + + for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { + if (strcmp(ksp->ks_module, module) == 0 && + (name == NULL || strcmp(ksp->ks_name, name) == 0) && + (instance == -1 || ksp->ks_instance == instance)) { + if (kstat_read(kc, ksp, NULL) == -1) { + *errp = -1; + return (list); + } + /* + * Find the kstat in the existing list: + * If we find one for the same instance and with the + * same ks_kid we'll save it as old_kstat. + * If we find one for the same instance but with a + * different ks_kid we'll removed it. + */ + for (sdpp = sdp = list; sdp; sdp = sdp->sd_next) { + if (ksp->ks_instance == + sdp->sd_nks.ks_instance) { + if (ksp->ks_kid == sdp->sd_nks.ks_kid) { + kstat_clone(&sdp->sd_nks, + &sdp->sd_oks, 1); + } else { + kstat_erase(&sdp->sd_oks); + } + kstat_clone(ksp, &sdp->sd_nks, 1); + sdp->sd_state |= SD_UPDATED; + break; + } + sdpp = sdp; + } + /* add a new kstat instance */ + if (!sdp) { + /* first instance */ + if (!list) { + list = sdata_new(ksp); + list->sd_state |= SD_UPDATED; + } else { + sdpp->sd_next = sdata_new(ksp); + sdpp->sd_next->sd_state |= SD_UPDATED; + } + } + } + } + + /* remove untouched statistics */ + sdp = list; + sdpp = NULL; + while (sdp != NULL) { + + if (sdp->sd_state & SD_UPDATED) { + sdp->sd_state &= ~SD_UPDATED; + sdpp = sdp; + sdp = sdp->sd_next; + } else { + sdata_t *tmp; + + if (sdpp == NULL) + list = sdp->sd_next; + else + sdpp->sd_next = sdp->sd_next; + tmp = sdp->sd_next; + sdata_free(sdp); + sdp = tmp; + } + } + + *errp = 0; + return (list); +} + +/* + * Update the pset assignment information for each cpu in the statistic + * data list. + */ +static void +update_cpu_list(sdata_t *list) +{ + sdata_t *sdp; + + for (sdp = list; sdp; sdp = sdp->sd_next) { + /* for new CPU create a new user data object */ + if (sdp->sd_udata == NULL) { + sdp->sd_udata = ZALLOC(sizeof (pset_ud_t)); + /* + * set its pset to invalid, so it will not be + * used in statistics calculation. + */ + SD_NPSET(sdp) = INVALID_SET; + } + /* copy the pset assignment information to the previous stat */ + SD_OPSET(sdp) = SD_NPSET(sdp); + /* set the current assignment */ + if (pset_assign(PS_QUERY, sdp->sd_nks.ks_instance, + &(SD_NPSET(sdp))) == -1) + SD_NPSET(sdp) = INVALID_SET; + } +} + +/* + * Update statistic data for pset. Calculate the CPU usage in a pset. + */ +static void +update_pset_stats(statistic_bag_t *sbag, sdata_t *list) +{ + sdata_t *sdp; + pset_statistic_bag_t *bag = (pset_statistic_bag_t *)sbag->bag; + uint64_t allticks, ust, kst, ist, wst; + + ust = kst = ist = wst = 0; + for (sdp = list; sdp; sdp = sdp->sd_next) { + /* + * only calculate for the asked pset id and if the cpu belongs + * to the same set in the previous and in the current snapshot. + * It means that the usage for CPUs that were rebound during + * the sampling interval are not charged to any set. + */ + if ((SD_OPSET(sdp) == SD_NPSET(sdp)) && + (SD_NPSET(sdp) == bag->pset_sb_sysid)) { + ust += delta(&sdp->sd_nks, &sdp->sd_oks, + "cpu_ticks_user", 0); + kst += delta(&sdp->sd_nks, &sdp->sd_oks, + "cpu_ticks_kernel", 0); + ist += delta(&sdp->sd_nks, &sdp->sd_oks, + "cpu_ticks_idle", 0); + wst += delta(&sdp->sd_nks, &sdp->sd_oks, + "cpu_ticks_wait", 0); + } + } + + if ((allticks = ust + kst + wst + ist) != 0) { + bag->pset_sb_used = + (double)(ust + kst) / allticks * bag->pset_sb_size; + } else { + bag->pset_sb_used = 0.0; + } +} diff --git a/usr/src/cmd/pools/poolstat/sa_libpool.c b/usr/src/cmd/pools/poolstat/sa_libpool.c new file mode 100644 index 0000000000..6b2642eed3 --- /dev/null +++ b/usr/src/cmd/pools/poolstat/sa_libpool.c @@ -0,0 +1,156 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * sa_libpool - libpool statistic adapter, collect statistic data provided + * by libpool. + */ + +#include <string.h> +#include <locale.h> +#include <assert.h> + +#include <pool.h> + +#include "utils.h" +#include "poolstat.h" + +typedef int (*prop_walk_cb_t) + (pool_conf_t *, pool_elem_t *, const char *, pool_value_t *, void *); + +/* user data used in the property walk callback function. */ +typedef struct { + int ud_result; + void* ud_bag; +} userdata_cb_t; + +static pool_conf_t *conf; +static const char *conf_loc; + +static void update_pset(statistic_bag_t *); + +/* + * If not NULL use the passed 'configuration' to access the pool framework, + * otherwise create and open a private access point. + */ +void +sa_libpool_init(void *configuration) +{ + if (configuration) { + conf = configuration; + } else { + conf_loc = pool_dynamic_location(); + if ((conf = pool_conf_alloc()) == NULL) + die(gettext(ERR_NOMEM)); + if (pool_conf_open(conf, conf_loc, PO_RDONLY | PO_UPDATE) + != PO_SUCCESS) + die(gettext(ERR_OPEN_STATIC), conf_loc, get_errstr()); + } +} + +/*ARGSUSED*/ +void +sa_libpool_update(statistic_bag_t *sbag, int flags) +{ + static int changed; + + /* The SA_REFRESH flag forces the update of local data structures. */ + if (flags & SA_REFRESH) { + changed = 0; + if (pool_conf_update(conf, &changed) != PO_SUCCESS) + die(gettext(ERR_CONF_UPDATE), get_errstr()); + sbag->sb_changed = changed; + } + if (strcmp(sbag->sb_type, PSET_TYPE_NAME) == 0) { + if (changed & POU_PSET || changed & POU_CPU) + ((pset_statistic_bag_t *)sbag->bag)->pset_sb_changed = + changed; + else + ((pset_statistic_bag_t *)sbag->bag)->pset_sb_changed = + 0; + update_pset(sbag); + } else if (strcmp(sbag->sb_type, POOL_TYPE_NAME) == 0) { + return; + } else { + die(gettext(ERR_UNSUPP_STYPE), sbag->sb_type); + } +} + +/* + * callback function to property walker, copies the property value from + * the passed 'pvalue' to the corresponding field in the statistic data bag. + */ +/*ARGSUSED*/ +static int +populate_userdata_cb(pool_conf_t *unused1, pool_elem_t *unused2, + const char *name, pool_value_t *pval, userdata_cb_t *ud) +{ + pset_statistic_bag_t *bag = (pset_statistic_bag_t *)ud->ud_bag; + + ud->ud_result = 0; + if (strcmp("pset.min", name) == 0) { + ud->ud_result = pool_value_get_uint64(pval, &bag->pset_sb_min); + } else if (strcmp("pset.max", name) == 0) { + ud->ud_result = pool_value_get_uint64(pval, &bag->pset_sb_max); + } else if (strcmp("pset.load", name) == 0) { + uint64_t load; + + ud->ud_result = pool_value_get_uint64(pval, &load); + bag->pset_sb_load = (double)load / 1000.0; + } else if (strcmp("pset.size", name) == 0) { + ud->ud_result = pool_value_get_uint64(pval, &bag->pset_sb_size); + } else if (strcmp("pset.sys_id", name) == 0) { + ud->ud_result = pool_value_get_int64(pval, &bag->pset_sb_sysid); + } + + return (0); +} + +/* + * Update statistic data for the procssor set with the name 'sbag->name'. + * Use 'sbag->bag' to store the data. + */ +static void +update_pset(statistic_bag_t *sbag) +{ + pool_resource_t *pset_reso; + pool_elem_t *pset_elem; + userdata_cb_t ud; + + ud.ud_bag = (void *) sbag->bag; + if ((pset_reso = pool_get_resource(conf, PSET_TYPE_NAME, sbag->sb_name)) + == NULL) + die(gettext(ERR_STATS_RES_N), sbag->sb_name, get_errstr()); + if ((pset_elem = pool_resource_to_elem(conf, pset_reso)) == NULL) + die(gettext(ERR_STATS_RES_N), sbag->sb_name, get_errstr()); + + /* use the property walker to collect the resource properties */ + if (pool_walk_properties(conf, pset_elem, &ud, + (prop_walk_cb_t)populate_userdata_cb) == -1) + die(gettext(ERR_STATS_RES_N), sbag->sb_name, get_errstr()); +} |