Current section
Files
Jump to
Current section
Files
c_src/ekstat.h
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Copyright 2013 David Hoeppner. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright 2013 Pagoda Box, Inc. All rights reserved.
*/
#ifndef _STAT_EKSTAT_H
#define _STAT_EKSTAT_H
/*
* Structures needed by the kstat reader functions.
*/
#include <sys/var.h>
#include <sys/utsname.h>
#include <sys/sysinfo.h>
#include <sys/flock.h>
#include <sys/dnlc.h>
#include <regex.h>
#include <nfs/nfs.h>
#include <nfs/nfs_clnt.h>
#ifdef __sparc
#include <vm/hat_sfmmu.h>
#include <sys/simmstat.h>
#include <sys/sysctrl.h>
#include <sys/fhc.h>
#endif
#include "erl_nif.h"
#define KSTAT_DATA_HRTIME (KSTAT_DATA_STRING + 1)
typedef union ks_value {
char c[16];
int32_t i32;
uint32_t ui32;
struct {
union {
char *ptr;
char __pad[8];
} addr;
uint32_t len;
} str;
int64_t i64;
uint64_t ui64;
} ks_value_t;
#define SAVE_HRTIME(R, I, S, N) \
{ \
ks_value_t v; \
v.ui64 = S->N; \
nvpair_insert(R, I, #N, &v, KSTAT_DATA_UINT64); \
}
#define SAVE_INT32(R, I, S, N) \
{ \
ks_value_t v; \
v.i32 = S->N; \
nvpair_insert(R, I, #N, &v, KSTAT_DATA_INT32); \
}
#define SAVE_UINT32(R, I, S, N) \
{ \
ks_value_t v; \
v.ui32 = S->N; \
nvpair_insert(R, I, #N, &v, KSTAT_DATA_UINT32); \
}
#define SAVE_INT64(R, I, S, N) \
{ \
ks_value_t v; \
v.i64 = S->N; \
nvpair_insert(R, I, #N, &v, KSTAT_DATA_INT64); \
}
#define SAVE_UINT64(R, I, S, N) \
{ \
ks_value_t v; \
v.ui64 = S->N; \
nvpair_insert(R, I, #N, &v, KSTAT_DATA_UINT64); \
}
/*
* We dont want const "strings" because we free
* the instances later.
*/
#define SAVE_STRING(R, I, S, N) \
{ \
ks_value_t v; \
v.str.addr.ptr = ks_safe_strdup(R, S->N); \
v.str.len = strlen(S->N); \
nvpair_insert(R, I, #N, &v, KSTAT_DATA_STRING); \
}
#define SAVE_HRTIME_X(R, I, N, V) \
{ \
ks_value_t v; \
v.ui64 = V; \
nvpair_insert(R, I, N, &v, KSTAT_DATA_HRTIME); \
}
#define SAVE_INT32_X(R, I, N, V) \
{ \
ks_value_t v; \
v.i32 = V; \
nvpair_insert(R, I, N, &v, KSTAT_DATA_INT32); \
}
#define SAVE_UINT32_X(R, I, N, V) \
{ \
ks_value_t v; \
v.ui32 = V; \
nvpair_insert(R, I, N, &v, KSTAT_DATA_UINT32); \
}
#define SAVE_UINT64_X(R, I, N, V) \
{ \
ks_value_t v; \
v.ui64 = V; \
nvpair_insert(R, I, N, &v, KSTAT_DATA_UINT64); \
}
#define SAVE_STRING_X(R, I, N, V) \
{ \
ks_value_t v; \
v.str.addr.ptr = ks_safe_strdup(R, V); \
v.str.len = (V) ? strlen(V) : 0; \
nvpair_insert(R, I, N, &v, KSTAT_DATA_STRING); \
}
#define SAVE_CHAR_X(R, I, N, V) \
{ \
ks_value_t v; \
(void) asprintf(&v.str.addr.ptr, "%c", V); \
v.str.len = 1; \
nvpair_insert(R, I, N, &v, KSTAT_DATA_STRING); \
}
typedef struct ks_instance {
list_node_t ks_next;
char ks_name[KSTAT_STRLEN];
char ks_module[KSTAT_STRLEN];
char ks_class[KSTAT_STRLEN];
int ks_instance;
uchar_t ks_type;
hrtime_t ks_snaptime;
list_t ks_nvlist;
} ks_instance_t;
typedef struct ks_nvpair {
list_node_t nv_next;
char name[KSTAT_STRLEN];
uchar_t data_type;
ks_value_t value;
} ks_nvpair_t;
typedef struct ks_pattern {
boolean_t free;
char *pstr;
regex_t preg;
} ks_pattern_t;
typedef struct ks_selector {
ks_pattern_t ks_class;
ks_pattern_t ks_module;
ks_pattern_t ks_instance;
ks_pattern_t ks_name;
ks_pattern_t ks_statistic;
} ks_selector_t;
typedef struct ks_returner {
ErlNifEnv *env;
boolean_t ready;
ERL_NIF_TERM term;
} ks_returner_t;
static void nvpair_insert(ks_returner_t *, ks_instance_t *, char *, ks_value_t *, uchar_t);
static int compare_instances(ks_instance_t *, ks_instance_t *);
static char *ks_safe_strdup(ks_returner_t *, char *);
static boolean_t ks_match(ks_returner_t *, const char *, ks_pattern_t *);
static ks_selector_t *new_selector(ks_returner_t *);
static void free_pattern(ks_pattern_t *);
static void free_selector(ks_selector_t *);
/* Raw kstat readers */
static void save_cpu_stat(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_var(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_ncstats(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_sysinfo(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_vminfo(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_nfs(ks_returner_t *, kstat_t *, ks_instance_t *);
#ifdef __sparc
static void save_sfmmu_global_stat(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_sfmmu_tsbsize_stat(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_simmstat(ks_returner_t *, kstat_t *, ks_instance_t *);
/* Helper function for save_temperature() */
static char *short_array_to_string(short *, int);
static void save_temperature(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_temp_over(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_ps_shadow(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_fault_list(ks_returner_t *, kstat_t *, ks_instance_t *);
#endif
/* Named kstat readers */
static void save_named(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_intr(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_io(ks_returner_t *, kstat_t *, ks_instance_t *);
static void save_timer(ks_returner_t *, kstat_t *, ks_instance_t *);
/* Typedef for raw kstat reader functions */
typedef void (*kstat_raw_reader_t)(ks_returner_t *, kstat_t *, ks_instance_t *);
static struct {
kstat_raw_reader_t fn;
char *name;
} ks_raw_lookup[] = {
/* Function name kstat name */
{save_cpu_stat, "cpu_stat:cpu_stat"},
{save_var, "unix:var"},
{save_ncstats, "unix:ncstats"},
{save_sysinfo, "unix:sysinfo"},
{save_vminfo, "unix:vminfo"},
{save_nfs, "nfs:mntinfo"},
#ifdef __sparc
{save_sfmmu_global_stat, "unix:sfmmu_global_stat"},
{save_sfmmu_tsbsize_stat, "unix:sfmmu_tsbsize_stat"},
{save_simmstat, "unix:simm-status"},
{save_temperature, "unix:temperature"},
{save_temp_over, "unix:temperature override"},
{save_ps_shadow, "unix:ps_shadow"},
{save_fault_list, "unix:fault_list"},
#endif
{NULL, NULL},
};
static kstat_raw_reader_t lookup_raw_kstat_fn(char *, char *);
static ERL_NIF_TERM ks_nvpair_term(ks_returner_t *, ks_nvpair_t *);
static ERL_NIF_TERM ks_instance_term(ks_returner_t *, ks_instance_t *, ERL_NIF_TERM);
static ks_returner_t *new_returner(ErlNifEnv *);
static ERL_NIF_TERM ks_returner_term(ks_returner_t *, ERL_NIF_TERM);
static void ks_selector_arg(ks_returner_t *, ks_pattern_t *, ERL_NIF_TERM);
/*
* Erlang NIF functions
*/
typedef struct ks_handle_t {
kid_t ks_id;
kstat_ctl_t *ks_ctl;
/* Sorted list of kstat instances */
list_t instances_list;
} ks_handle_t;
#define EKSTAT_ATOM(A) enif_make_atom(ret->env, A)
#define EKSTAT_DOUBLE(A) enif_make_double(ret->env, A)
#define EKSTAT_INT(A) enif_make_int(ret->env, A)
#define EKSTAT_INT64(A) enif_make_int64(ret->env, A)
#define EKSTAT_STRING(A) enif_make_string(ret->env, A, ERL_NIF_LATIN1)
#define EKSTAT_TUPLE2(A, B) enif_make_tuple2(ret->env, A, B)
#define EKSTAT_TUPLE3(A, B, C) enif_make_tuple3(ret->env, A, B, C)
#define EKSTAT_TUPLE4(A, B, C, D) enif_make_tuple4(ret->env, A, B, C, D)
#define EKSTAT_TUPLE5(A, B, C, D, E) enif_make_tuple5(ret->env, A, B, C, D, E)
#define EKSTAT_UINT(A) enif_make_uint(ret->env, A)
#define EKSTAT_UINT64(A) enif_make_uint64(ret->env, A)
#define EKSTAT_ERROR(A) EKSTAT_TUPLE2(EKSTAT_ATOM("error"), EKSTAT_TUPLE2(EKSTAT_ATOM("kstat"), EKSTAT_STRING(A)))
#define EKSTAT_OK(A) EKSTAT_TUPLE2(EKSTAT_ATOM("ok"), A)
#define EKSTAT_RETURN(A) ks_returner_term(ret, A)
static void handle_dtor(ErlNifEnv *, void *);
static int load(ErlNifEnv *, void **, ERL_NIF_TERM);
static int upgrade(ErlNifEnv *, void **, void **, ERL_NIF_TERM);
static ERL_NIF_TERM open_nif(ErlNifEnv *, int, const ERL_NIF_TERM[]);
static ERL_NIF_TERM update_nif(ErlNifEnv *, int, const ERL_NIF_TERM[]);
static ERL_NIF_TERM read_nif(ErlNifEnv *, int, const ERL_NIF_TERM[]);
static ERL_NIF_TERM clear_nif(ErlNifEnv *, int, const ERL_NIF_TERM[]);
static ErlNifFunc nif_funcs[] = {
{"open", 0, open_nif},
{"update", 1, update_nif},
{"read", 1, read_nif},
{"read", 2, read_nif},
{"read", 3, read_nif},
{"read", 4, read_nif},
{"read", 5, read_nif},
{"read", 6, read_nif},
{"clear", 1, clear_nif}
};
#endif /* _STAT_EKSTAT_H */