diff options
| author | tomee <none@none> | 2006-02-16 12:15:27 -0800 |
|---|---|---|
| committer | tomee <none@none> | 2006-02-16 12:15:27 -0800 |
| commit | fb3fb4f3d76d55b64440afd0af72775dfad3bd1d (patch) | |
| tree | befe8fec5ad60327cead19dcdbe6773c3e7d00b5 /usr/src/lib/libdtrace_jni/common/dtj_jnitab.c | |
| parent | 5e985db5e665b4363a8154fb1870b3895ca33192 (diff) | |
| download | illumos-gate-fb3fb4f3d76d55b64440afd0af72775dfad3bd1d.tar.gz | |
PSARC 2006/054 DTrace JNI Binding
6384263 PSARC 2006/054 DTrace JNI Binding
Diffstat (limited to 'usr/src/lib/libdtrace_jni/common/dtj_jnitab.c')
| -rw-r--r-- | usr/src/lib/libdtrace_jni/common/dtj_jnitab.c | 853 |
1 files changed, 853 insertions, 0 deletions
diff --git a/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c b/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c new file mode 100644 index 0000000000..f0f4cc6c8e --- /dev/null +++ b/usr/src/lib/libdtrace_jni/common/dtj_jnitab.c @@ -0,0 +1,853 @@ +/* + * 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. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdlib.h> +#include <stddef.h> +#include <limits.h> +#include <strings.h> +#include <pthread.h> +#include <dtrace_jni.h> + +/* + * dtj_jnitab.c defines the JNI table of classes, methods, and fields belonging + * to the Java DTrace API. Another JNI table defining classes from the JDK is + * defined in dtj_util.c. Utility functions specific to the Java DTrace API are + * also defined here, while general utilities are defined in dtj_util.c. + */ + +static uu_list_pool_t *g_request_pool = NULL; +static uu_list_pool_t *g_program_pool = NULL; +static uu_list_pool_t *g_aggval_pool = NULL; + +static boolean_t dtj_check_request_pool(void); +static boolean_t dtj_check_program_pool(void); +static boolean_t dtj_check_aggval_pool(void); + +/* LocalConsumer */ +jclass g_caller_jc = 0; +jmethodID g_gethandle_jm = 0; +jmethodID g_sethandle_jm = 0; +jmethodID g_pdatanext_jm = 0; +jmethodID g_drop_jm = 0; +jmethodID g_error_jm = 0; +jmethodID g_proc_jm = 0; +jmethodID g_interval_began_jm = 0; +jmethodID g_interval_ended_jm = 0; +jfieldID g_consumer_lock_jf = 0; + +/* DTraceException */ +jclass g_dtx_jc = 0; +jmethodID g_dtxinit_jm = 0; + +/* InterfaceAttributes */ +jclass g_attr_jc = 0; +jmethodID g_attrinit_jm = 0; +jmethodID g_attrset_name_jm = 0; +jmethodID g_attrset_data_jm = 0; +jmethodID g_attrset_class_jm = 0; + +/* ProbeDescription */ +jclass g_probedesc_jc = 0; +jmethodID g_probedescinit_jm = 0; +jfieldID g_probedesc_id_jf = 0; + +/* ProbeInfo */ +jclass g_probeinfo_jc = 0; +jmethodID g_probeinfoinit_jm = 0; + +/* Probe */ +jclass g_probe_jc = 0; +jmethodID g_probeinit_jm = 0; + +/* Program */ +jclass g_program_jc = 0; +jmethodID g_proginit_jm = 0; +jfieldID g_progid_jf = 0; +jfieldID g_proginfo_jf = 0; + +/* Program.File */ +jclass g_programfile_jc = 0; +jmethodID g_fproginit_jm = 0; + +/* ProgramInfo */ +jclass g_proginfo_jc = 0; +jmethodID g_proginfoinit_jm = 0; + +/* Flow */ +jclass g_flow_jc = 0; +jmethodID g_flowinit_jm = 0; + +/* ProbeData */ +jclass g_pdata_jc = 0; +jmethodID g_pdatainit_jm = 0; +jmethodID g_pdataadd_jm = 0; +jmethodID g_pdataadd_rec_jm = 0; +jmethodID g_pdataadd_trace_jm = 0; +jmethodID g_pdataadd_stack_jm = 0; +jmethodID g_pdataadd_printf_jm = 0; +jmethodID g_pdataadd_printa_jm = 0; +jmethodID g_pdatainvalidate_printa_jm = 0; +jmethodID g_pdataadd_aggrec_jm = 0; +jmethodID g_pdataadd_printa_str_jm = 0; +jmethodID g_pdataadd_exit_jm = 0; +jmethodID g_pdataattach_jm = 0; +jmethodID g_pdataset_formatted_jm = 0; +jmethodID g_pdataclear_jm = 0; + +/* Drop */ +jclass g_drop_jc = 0; +jmethodID g_dropinit_jm = 0; + +/* Error */ +jclass g_error_jc = 0; +jmethodID g_errinit_jm = 0; + +/* ProcessState */ +jclass g_process_jc = 0; +jmethodID g_procinit_jm = 0; +jmethodID g_procexit_jm = 0; + +/* Aggregate */ +jclass g_agg_jc = 0; +jmethodID g_agginit_jm = 0; +jmethodID g_aggaddrec_jm = 0; + +/* AggregateSpec */ +jclass g_aggspec_jc = 0; +jmethodID g_aggspec_included_jm = 0; +jmethodID g_aggspec_cleared_jm = 0; + +/* Tuple */ +jclass g_tuple_jc = 0; +jmethodID g_tupleinit_jm = 0; +jmethodID g_tupleadd_jm = 0; +jmethodID g_tuplesize_jm = 0; +jfieldID g_tuple_EMPTY_jsf = 0; + +/* AggregationRecord */ +jclass g_aggrec_jc = 0; +jmethodID g_aggrecinit_jm = 0; +jmethodID g_aggrecget_tuple_jm = 0; + +/* SumValue */ +jclass g_aggsum_jc = 0; +jmethodID g_aggsuminit_jm = 0; + +/* CountValue */ +jclass g_aggcount_jc = 0; +jmethodID g_aggcountinit_jm = 0; + +/* AvgValue */ +jclass g_aggavg_jc = 0; +jmethodID g_aggavginit_jm = 0; + +/* MinValue */ +jclass g_aggmin_jc = 0; +jmethodID g_aggmininit_jm = 0; + +/* MaxValue */ +jclass g_aggmax_jc = 0; +jmethodID g_aggmaxinit_jm = 0; + +/* KernelStackRecord */ +jclass g_stack_jc = 0; +jmethodID g_parsestack_jsm = 0; +jmethodID g_stackinit_jm = 0; +jmethodID g_stackset_frames_jm = 0; + +/* UserStackRecord */ +jclass g_ustack_jc = 0; +jmethodID g_ustackinit_jm = 0; +jmethodID g_ustackset_frames_jm = 0; + +/* Distribution */ +jclass g_adist_jc = 0; +jmethodID g_dist_normal_jm = 0; + +/* LogDistribution */ +jclass g_dist_jc = 0; +jmethodID g_distinit_jm = 0; + +/* LinearDistribution */ +jclass g_ldist_jc = 0; +jmethodID g_ldistinit_jm = 0; + + +static dtj_status_t +dtj_table_load(JNIEnv *jenv) +{ + static const dtj_table_entry_t table[] = { + /* LocalConsumer */ + { JCLASS, &g_caller_jc, + "org/opensolaris/os/dtrace/LocalConsumer" }, + { JMETHOD, &g_gethandle_jm, "getHandle", "()I" }, + { JMETHOD, &g_sethandle_jm, "setHandle", "(I)V" }, + { JMETHOD, &g_pdatanext_jm, "nextProbeData", + "(Lorg/opensolaris/os/dtrace/ProbeData;)V" }, + { JMETHOD, &g_drop_jm, "dataDropped", + "(Lorg/opensolaris/os/dtrace/Drop;)V" }, + { JMETHOD, &g_error_jm, "errorEncountered", + "(Lorg/opensolaris/os/dtrace/Error;)V" }, + { JMETHOD, &g_proc_jm, "processStateChanged", + "(Lorg/opensolaris/os/dtrace/ProcessState;)V" }, + { JMETHOD, &g_interval_began_jm, "intervalBegan", "()V" }, + { JMETHOD, &g_interval_ended_jm, "intervalEnded", "()V" }, + { JFIELD, &g_consumer_lock_jf, "consumerLock", + "Ljava/lang/Object;" }, + + /* DTraceException */ + { JCLASS, &g_dtx_jc, + "org/opensolaris/os/dtrace/DTraceException" }, + { JMETHOD, &g_dtxinit_jm, CONSTRUCTOR, + "(Ljava/lang/String;)V" }, + + /* InterfaceAttributes */ + { JCLASS, &g_attr_jc, + "org/opensolaris/os/dtrace/InterfaceAttributes" }, + { JMETHOD, &g_attrinit_jm, CONSTRUCTOR, "()V" }, + { JMETHOD, &g_attrset_name_jm, "setNameStability", + "(Ljava/lang/String;)V" }, + { JMETHOD, &g_attrset_data_jm, "setDataStability", + "(Ljava/lang/String;)V" }, + { JMETHOD, &g_attrset_class_jm, "setDependencyClass", + "(Ljava/lang/String;)V" }, + + /* ProbeDescription */ + { JCLASS, &g_probedesc_jc, + "org/opensolaris/os/dtrace/ProbeDescription" }, + { JMETHOD, &g_probedescinit_jm, CONSTRUCTOR, + "(Ljava/lang/String;Ljava/lang/String;" + "Ljava/lang/String;Ljava/lang/String;)V" }, + { JFIELD, &g_probedesc_id_jf, "id", "I" }, + + /* ProbeInfo */ + { JCLASS, &g_probeinfo_jc, + "org/opensolaris/os/dtrace/ProbeInfo" }, + { JMETHOD, &g_probeinfoinit_jm, CONSTRUCTOR, + "(Lorg/opensolaris/os/dtrace/InterfaceAttributes;" + "Lorg/opensolaris/os/dtrace/InterfaceAttributes;" + ")V" }, + + /* Probe */ + { JCLASS, &g_probe_jc, "org/opensolaris/os/dtrace/Probe" }, + { JMETHOD, &g_probeinit_jm, CONSTRUCTOR, + "(Lorg/opensolaris/os/dtrace/ProbeDescription;" + "Lorg/opensolaris/os/dtrace/ProbeInfo;)V" }, + + /* Program */ + { JCLASS, &g_program_jc, + "org/opensolaris/os/dtrace/Program" }, + { JMETHOD, &g_proginit_jm, CONSTRUCTOR, "()V" }, + { JFIELD, &g_progid_jf, "id", "I" }, + { JFIELD, &g_proginfo_jf, "info", + "Lorg/opensolaris/os/dtrace/ProgramInfo;" }, + + /* Program.File */ + { JCLASS, &g_programfile_jc, + "org/opensolaris/os/dtrace/Program$File" }, + { JMETHOD, &g_fproginit_jm, CONSTRUCTOR, "()V" }, + + /* ProgramInfo */ + { JCLASS, &g_proginfo_jc, + "org/opensolaris/os/dtrace/ProgramInfo" }, + { JMETHOD, &g_proginfoinit_jm, CONSTRUCTOR, + "(Lorg/opensolaris/os/dtrace/InterfaceAttributes;" + "Lorg/opensolaris/os/dtrace/InterfaceAttributes;" + "I)V" }, + + /* Flow */ + { JCLASS, &g_flow_jc, "org/opensolaris/os/dtrace/Flow" }, + { JMETHOD, &g_flowinit_jm, CONSTRUCTOR, + "(Ljava/lang/String;I)V" }, + + /* ProbeData */ + { JCLASS, &g_pdata_jc, + "org/opensolaris/os/dtrace/ProbeData" }, + { JMETHOD, &g_pdatainit_jm, CONSTRUCTOR, + "(IILorg/opensolaris/os/dtrace/ProbeDescription;" + "Lorg/opensolaris/os/dtrace/Flow;I)V" }, + { JMETHOD, &g_pdataadd_jm, "addDataElement", + "(Ljava/lang/Object;)V" }, + { JMETHOD, &g_pdataadd_rec_jm, "addRecord", + "(Lorg/opensolaris/os/dtrace/Record;)V" }, + { JMETHOD, &g_pdataadd_trace_jm, "addTraceRecord", "(I)V" }, + { JMETHOD, &g_pdataadd_stack_jm, "addStackRecord", + "(ILjava/lang/String;)V" }, + { JMETHOD, &g_pdataadd_printf_jm, "addPrintfRecord", "()V" }, + { JMETHOD, &g_pdataadd_printa_jm, "addPrintaRecord", "(JZ)V" }, + { JMETHOD, &g_pdatainvalidate_printa_jm, + "invalidatePrintaRecord", "()V" }, + { JMETHOD, &g_pdataadd_aggrec_jm, "addAggregationRecord", + "(Ljava/lang/String;J" + "Lorg/opensolaris/os/dtrace/AggregationRecord;)V" }, + { JMETHOD, &g_pdataadd_printa_str_jm, + "addPrintaFormattedString", + "(Lorg/opensolaris/os/dtrace/Tuple;" + "Ljava/lang/String;)V" }, + { JMETHOD, &g_pdataadd_exit_jm, "addExitRecord", "(I)V" }, + { JMETHOD, &g_pdataattach_jm, "attachRecordElements", + "(II)V" }, + { JMETHOD, &g_pdataset_formatted_jm, "setFormattedString", + "(Ljava/lang/String;)V" }, + { JMETHOD, &g_pdataclear_jm, "clearNativeElements", "()V" }, + + /* Drop */ + { JCLASS, &g_drop_jc, "org/opensolaris/os/dtrace/Drop" }, + { JMETHOD, &g_dropinit_jm, CONSTRUCTOR, + "(ILjava/lang/String;JJLjava/lang/String;)V" }, + + /* Error */ + { JCLASS, &g_error_jc, "org/opensolaris/os/dtrace/Error" }, + { JMETHOD, &g_errinit_jm, CONSTRUCTOR, + "(Lorg/opensolaris/os/dtrace/ProbeDescription;IIII" + "Ljava/lang/String;JLjava/lang/String;)V" }, + + /* ProcessState */ + { JCLASS, &g_process_jc, + "org/opensolaris/os/dtrace/ProcessState" }, + { JMETHOD, &g_procinit_jm, CONSTRUCTOR, + "(ILjava/lang/String;ILjava/lang/String;" + "Ljava/lang/Integer;Ljava/lang/String;)V" }, + { JMETHOD, &g_procexit_jm, "setExitStatus", "(I)V" }, + + /* Aggregate */ + { JCLASS, &g_agg_jc, "org/opensolaris/os/dtrace/Aggregate" }, + { JMETHOD, &g_agginit_jm, CONSTRUCTOR, "(J)V" }, + { JMETHOD, &g_aggaddrec_jm, "addRecord", + "(Ljava/lang/String;J" + "Lorg/opensolaris/os/dtrace/AggregationRecord;)V" }, + + /* AggregateSpec */ + { JCLASS, &g_aggspec_jc, + "org/opensolaris/os/dtrace/AggregateSpec" }, + { JMETHOD, &g_aggspec_included_jm, "isIncluded", + "(Ljava/lang/String;)Z" }, + { JMETHOD, &g_aggspec_cleared_jm, "isCleared", + "(Ljava/lang/String;)Z" }, + + /* Tuple */ + { JCLASS, &g_tuple_jc, "org/opensolaris/os/dtrace/Tuple" }, + { JMETHOD, &g_tupleinit_jm, CONSTRUCTOR, "()V" }, + { JMETHOD, &g_tupleadd_jm, "addElement", + "(Ljava/lang/Object;)V" }, + { JMETHOD, &g_tuplesize_jm, "size", "()I" }, + { JFIELD_STATIC, &g_tuple_EMPTY_jsf, "EMPTY", + "Lorg/opensolaris/os/dtrace/Tuple;" }, + + /* AggregationRecord */ + { JCLASS, &g_aggrec_jc, + "org/opensolaris/os/dtrace/AggregationRecord" }, + { JMETHOD, &g_aggrecinit_jm, CONSTRUCTOR, + "(Lorg/opensolaris/os/dtrace/Tuple;" + "Lorg/opensolaris/os/dtrace/AggregationValue;)V" }, + { JMETHOD, &g_aggrecget_tuple_jm, "getTuple", + "()Lorg/opensolaris/os/dtrace/Tuple;" }, + + /* SumValue */ + { JCLASS, &g_aggsum_jc, + "org/opensolaris/os/dtrace/SumValue" }, + { JMETHOD, &g_aggsuminit_jm, CONSTRUCTOR, "(J)V" }, + + /* CountValue */ + { JCLASS, &g_aggcount_jc, + "org/opensolaris/os/dtrace/CountValue" }, + { JMETHOD, &g_aggcountinit_jm, CONSTRUCTOR, "(J)V" }, + + /* AvgValue */ + { JCLASS, &g_aggavg_jc, + "org/opensolaris/os/dtrace/AvgValue" }, + { JMETHOD, &g_aggavginit_jm, CONSTRUCTOR, "(JJJ)V" }, + + /* MinValue */ + { JCLASS, &g_aggmin_jc, + "org/opensolaris/os/dtrace/MinValue" }, + { JMETHOD, &g_aggmininit_jm, CONSTRUCTOR, "(J)V" }, + + /* MaxValue */ + { JCLASS, &g_aggmax_jc, + "org/opensolaris/os/dtrace/MaxValue" }, + { JMETHOD, &g_aggmaxinit_jm, CONSTRUCTOR, "(J)V" }, + + /* KernelStackRecord */ + { JCLASS, &g_stack_jc, + "org/opensolaris/os/dtrace/KernelStackRecord" }, + { JMETHOD_STATIC, &g_parsestack_jsm, "parse", + "(Ljava/lang/String;)" + "[Lorg/opensolaris/os/dtrace/StackFrame;" }, + { JMETHOD, &g_stackinit_jm, CONSTRUCTOR, "([B)V" }, + { JMETHOD, &g_stackset_frames_jm, "setStackFrames", + "([Lorg/opensolaris/os/dtrace/StackFrame;)V" }, + + /* UserStackRecord */ + { JCLASS, &g_ustack_jc, + "org/opensolaris/os/dtrace/UserStackRecord" }, + { JMETHOD, &g_ustackinit_jm, CONSTRUCTOR, "(I[B)V" }, + { JMETHOD, &g_ustackset_frames_jm, "setStackFrames", + "([Lorg/opensolaris/os/dtrace/StackFrame;)V" }, + + /* Distribution */ + { JCLASS, &g_adist_jc, + "org/opensolaris/os/dtrace/Distribution" }, + { JMETHOD, &g_dist_normal_jm, "normalizeBuckets", "(J)V" }, + + /* LogDistribution */ + { JCLASS, &g_dist_jc, + "org/opensolaris/os/dtrace/LogDistribution" }, + { JMETHOD, &g_distinit_jm, CONSTRUCTOR, "([J)V" }, + + /* LinearDistribution */ + { JCLASS, &g_ldist_jc, + "org/opensolaris/os/dtrace/LinearDistribution" }, + { JMETHOD, &g_ldistinit_jm, CONSTRUCTOR, "(JJ[J)V" }, + + { DTJ_TYPE_END } + }; + + return (dtj_cache_jni_classes(jenv, table)); +} + +dtj_status_t +dtj_load(JNIEnv *jenv) +{ + if (dtj_load_common(jenv) != DTJ_OK) { + /* Java Error pending */ + return (DTJ_ERR); + } + + return (dtj_table_load(jenv)); +} + +static boolean_t +dtj_check_request_pool(void) +{ + if (!g_request_pool) { + g_request_pool = uu_list_pool_create("g_request_pool", + sizeof (dtj_request_t), + offsetof(dtj_request_t, dtjr_node), + dtj_pointer_list_entry_cmp, + (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); + if (!g_request_pool) { + return (B_FALSE); + } + } + return (B_TRUE); +} + +dtj_request_t * +dtj_request_create(JNIEnv *jenv, dtj_request_type_t type, ...) +{ + dtj_request_t *r; + + if (!dtj_check_request_pool()) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate request pool"); + return (NULL); + } + + r = uu_zalloc(sizeof (dtj_request_t)); + if (r) { + uu_list_node_init(r, &r->dtjr_node, g_request_pool); + r->dtjr_type = type; + r->dtjr_args = dtj_string_list_create(); + if (r->dtjr_args) { + va_list ap; + const char *arg; + int i, len; + + va_start(ap, type); + switch (type) { + case DTJ_REQUEST_OPTION: + len = 2; + break; + default: + len = 0; + } + + for (i = 0; i < len; ++i) { + arg = va_arg(ap, char *); + if (!dtj_string_list_add(r->dtjr_args, arg)) { + dtj_throw_out_of_memory(jenv, + "Failed to add request arg"); + uu_list_node_fini(r, &r->dtjr_node, + g_request_pool); + dtj_request_destroy(r, NULL); + r = NULL; + } + } + va_end(ap); + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate request arglist"); + uu_list_node_fini(r, &r->dtjr_node, g_request_pool); + dtj_request_destroy(r, NULL); + r = NULL; + } + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate request"); + } + + return (r); +} + +static boolean_t +dtj_check_program_pool(void) +{ + if (!g_program_pool) { + g_program_pool = uu_list_pool_create("g_program_pool", + sizeof (dtj_program_t), + offsetof(dtj_program_t, dtjp_node), + dtj_pointer_list_entry_cmp, + (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); + if (!g_program_pool) { + return (B_FALSE); + } + } + return (B_TRUE); +} + +dtj_program_t * +dtj_program_create(JNIEnv *jenv, dtj_program_type_t type, const char *name) +{ + dtj_program_t *p; + + if (!dtj_check_program_pool()) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate program pool"); + return (NULL); + } + + p = uu_zalloc(sizeof (dtj_program_t)); + if (p) { + char *program_name; + + uu_list_node_init(p, &p->dtjp_node, g_program_pool); + p->dtjp_type = type; + program_name = malloc((size_t) + (sizeof (char)) * (strlen(name) + 1)); + if (program_name) { + (void) strcpy(program_name, name); + p->dtjp_name = program_name; + p->dtjp_enabled = B_FALSE; + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate program name"); + uu_list_node_fini(p, &p->dtjp_node, g_program_pool); + dtj_program_destroy(p, NULL); + p = NULL; + } + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate program"); + } + + return (p); +} + +static boolean_t +dtj_check_aggval_pool(void) +{ + if (!g_aggval_pool) { + g_aggval_pool = uu_list_pool_create("g_aggval_pool", + sizeof (dtj_aggval_t), + offsetof(dtj_aggval_t, dtja_node), + dtj_pointer_list_entry_cmp, + (g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0)); + if (!g_aggval_pool) { + return (B_FALSE); + } + } + return (B_TRUE); +} + +dtj_aggval_t * +dtj_aggval_create(JNIEnv *jenv, jobject aggval, const char *aggname, + int64_t aggid) +{ + dtj_aggval_t *e; + + if (!dtj_check_aggval_pool()) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate aggval entry pool"); + return (NULL); + } + + e = uu_zalloc(sizeof (dtj_aggval_t)); + if (e) { + char *a_name; + + uu_list_node_init(e, &e->dtja_node, g_aggval_pool); + e->dtja_value = aggval; + a_name = malloc((size_t) + (sizeof (char)) * (strlen(aggname) + 1)); + if (a_name) { + (void) strcpy(a_name, aggname); + e->dtja_aggname = a_name; + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate aggregation name"); + uu_list_node_fini(e, &e->dtja_node, g_aggval_pool); + /* caller responsible for input java reference */ + e->dtja_value = NULL; + dtj_aggval_destroy(e, jenv); + e = NULL; + } + e->dtja_aggid = aggid; + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate aggval entry"); + } + + return (e); +} + +dtj_status_t +dtj_java_consumer_init(JNIEnv *jenv, dtj_java_consumer_t *jc) +{ + if (!dtj_check_aggval_pool()) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate aggval pool"); + return (DTJ_ERR); + } + + jc->dtjj_aggval_list = uu_list_create(g_aggval_pool, NULL, + (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); + if (!jc->dtjj_aggval_list) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate aggval list"); + return (DTJ_ERR); + } + + /* Does not throw exceptions */ + jc->dtjj_consumer_lock = (*jenv)->GetObjectField(jenv, jc->dtjj_caller, + g_consumer_lock_jf); + + return (DTJ_OK); +} + +void +dtj_java_consumer_fini(JNIEnv *jenv, dtj_java_consumer_t *jc) +{ + if (jc) { + if (jc->dtjj_probedata) { + (*jenv)->DeleteLocalRef(jenv, jc->dtjj_probedata); + jc->dtjj_probedata = NULL; + } + if (jc->dtjj_printa_buffer) { + (*jenv)->DeleteLocalRef(jenv, jc->dtjj_printa_buffer); + jc->dtjj_printa_buffer = NULL; + } + if (jc->dtjj_aggregate) { + (*jenv)->DeleteLocalRef(jenv, jc->dtjj_aggregate); + jc->dtjj_aggregate = NULL; + } + if (jc->dtjj_tuple) { + (*jenv)->DeleteLocalRef(jenv, jc->dtjj_tuple); + jc->dtjj_tuple = NULL; + } + if (jc->dtjj_aggval_list) { + dtj_list_destroy(jc->dtjj_aggval_list, + dtj_aggval_destroy, jenv); + jc->dtjj_aggval_list = NULL; + } + + /* + * aggregate_spec records an input argument to a native JNI + * function (a reference we did not create), so we are not + * responsible for it. + */ + jc->dtjj_aggregate_spec = NULL; + + /* + * probelist records an in-out argument to a native JNI function + * (a reference we did not create), so we are not responsible + * for it. + */ + jc->dtjj_probelist = NULL; + + if (jc->dtjj_exception) { + (*jenv)->DeleteLocalRef(jenv, jc->dtjj_exception); + jc->dtjj_exception = NULL; + } + (*jenv)->DeleteLocalRef(jenv, jc->dtjj_consumer_lock); + jc->dtjj_consumer_lock = NULL; + } +} + +dtj_consumer_t * +dtj_consumer_create(JNIEnv *jenv) +{ + dtj_consumer_t *c; + + if (!dtj_check_request_pool()) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate request pool"); + return (NULL); + } + + if (!dtj_check_program_pool()) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate program pool"); + return (NULL); + } + + c = uu_zalloc(sizeof (dtj_consumer_t)); + if (c) { + c->dtjc_request_list = uu_list_create(g_request_pool, NULL, + (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); + if (!c->dtjc_request_list) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate consumer request list"); + dtj_consumer_destroy(c); + return (NULL); + } + (void) pthread_mutex_init(&c->dtjc_request_list_lock, NULL); + + c->dtjc_program_list = uu_list_create(g_program_pool, NULL, + (g_dtj_util_debug ? UU_LIST_DEBUG : 0)); + if (!c->dtjc_program_list) { + dtj_throw_out_of_memory(jenv, + "Failed to allocate consumer program list"); + dtj_consumer_destroy(c); + return (NULL); + } + + c->dtjc_probedata_rec_i = 0; + c->dtjc_probedata_act = DTRACEACT_NONE; + c->dtjc_aggid = -1; + c->dtjc_expected = -1; + c->dtjc_state = DTJ_CONSUMER_INIT; + } else { + dtj_throw_out_of_memory(jenv, + "Failed to allocate consumer"); + } + + return (c); +} + +void +/* ARGSUSED */ +dtj_request_destroy(void *v, void *arg) +{ + if (v) { + dtj_request_t *r = v; + dtj_string_list_destroy(r->dtjr_args); + uu_list_node_fini(r, &r->dtjr_node, g_request_pool); + bzero(v, sizeof (dtj_request_t)); + uu_free(v); + } +} + +void +/* ARGSUSED */ +dtj_program_destroy(void *v, void *arg) +{ + if (v) { + dtj_program_t *p = v; + if (p->dtjp_name) { + free((void *)p->dtjp_name); + } + uu_list_node_fini(p, &p->dtjp_node, g_program_pool); + bzero(v, sizeof (dtj_program_t)); + uu_free(v); + } +} + +void +dtj_aggval_destroy(void *v, void *arg) +{ + if (v) { + dtj_aggval_t *a = v; + if (a->dtja_value && arg) { + JNIEnv *jenv = arg; + (*jenv)->DeleteLocalRef(jenv, a->dtja_value); + } + if (a->dtja_aggname) { + free((void *)a->dtja_aggname); + } + uu_list_node_fini(a, &a->dtja_node, g_aggval_pool); + bzero(v, sizeof (dtj_aggval_t)); + uu_free(v); + } +} + +/* + * Frees per-consumer state. Assumes that the DTrace handle has been closed + * already. + */ +void +dtj_consumer_destroy(dtj_consumer_t *c) +{ + if (c) { + dtj_list_destroy(c->dtjc_request_list, dtj_request_destroy, + NULL); + (void) pthread_mutex_destroy(&c->dtjc_request_list_lock); + dtj_list_destroy(c->dtjc_program_list, dtj_program_destroy, + NULL); + /* + * Cannot dtrace_proc_release the c->process_list proc + * elements here, because we need the dtrace handle for that. + * By the time this destructor is called, the dtrace handle is + * already closed. The proc elements are released in + * dtrace_jni.c _close(). + */ + if (c->dtjc_process_list) { + dtj_list_destroy(c->dtjc_process_list, NULL, NULL); + } + bzero(c, sizeof (dtj_consumer_t)); + uu_free(c); + } +} + +void +dtj_throw_dtrace_exception(dtj_java_consumer_t *jc, const char *fmt, ...) +{ + JNIEnv *jenv = jc->dtjj_jenv; + + va_list ap; + char msg[DTJ_MSG_SIZE]; + + jobject message = NULL; + jobject exception = NULL; + + va_start(ap, fmt); + (void) vsnprintf(msg, sizeof (msg), fmt, ap); + va_end(ap); + + message = dtj_NewStringNative(jenv, msg); + if (!message) { + return; /* java exception pending */ + } + + exception = (*jenv)->NewObject(jenv, g_dtx_jc, g_dtxinit_jm, message); + (*jenv)->DeleteLocalRef(jenv, message); + if (exception) { + (*jenv)->Throw(jenv, exception); + (*jenv)->DeleteLocalRef(jenv, exception); + } +} |
