/*
- * Copyright (C) 2016 - EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
- * 2016 - EfficiOS Inc., Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * SPDX-License-Identifier: LGPL-2.1-only
*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; only
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Copyright (C) 2016 EfficiOS Inc.
+ * Copyright (C) 2016 Alexandre Montplaisir <alexmonthy@efficios.com>
+ * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*/
#include "org_lttng_ust_agent_context_LttngContextApi.h"
#include <string.h>
#include <inttypes.h>
#include <lttng/ust-events.h>
-#include <lttng/ringbuffer-config.h>
-#include <lttng/ust-context-provider.h>
+#include <lttng/ringbuffer-context.h>
+#include <ust-context-provider.h>
-#include "helper.h"
+#include "ust-helper.h"
#include "lttng_ust_context.h"
-#define LTTNG_UST_JNI_CONTEXT_NAME_LEN 256
-/* TODO: the value should be variable length. */
-#define LTTNG_UST_JNI_VALUE_LEN 256
-
enum lttng_ust_jni_type {
JNI_TYPE_NULL = 0,
JNI_TYPE_INTEGER = 1,
JNI_TYPE_STRING = 8,
};
-struct lttng_ust_jni_ctx {
- char context_name[LTTNG_UST_JNI_CONTEXT_NAME_LEN];
+struct lttng_ust_jni_ctx_entry {
+ int32_t context_name_offset;
char type; /* enum lttng_ust_jni_type */
union {
int32_t _integer;
signed char _byte;
int16_t _short;
signed char _boolean;
- char _string[LTTNG_UST_JNI_VALUE_LEN];
+ int32_t _string_offset;
} value;
} __attribute__((packed));
/* TLS passing context info from JNI to callbacks. */
__thread struct lttng_ust_jni_tls lttng_ust_context_info_tls;
-static struct lttng_ust_jni_ctx *lookup_ctx_by_name(const char *ctx_name)
+static const char *get_ctx_string_at_offset(int32_t offset)
{
- struct lttng_ust_jni_ctx *ctx_array = lttng_ust_context_info_tls.ctx;
- int i, len = lttng_ust_context_info_tls.len / sizeof(struct lttng_ust_jni_ctx);
+ signed char *ctx_strings_array = lttng_ust_context_info_tls.ctx_strings;
+
+ if (offset < 0 || offset >= lttng_ust_context_info_tls.ctx_strings_len) {
+ return NULL;
+ }
+ return (const char *) (ctx_strings_array + offset);
+}
+
+static struct lttng_ust_jni_ctx_entry *lookup_ctx_by_name(const char *ctx_name)
+{
+ struct lttng_ust_jni_ctx_entry *ctx_entries_array = lttng_ust_context_info_tls.ctx_entries;
+ int i, len = lttng_ust_context_info_tls.ctx_entries_len / sizeof(struct lttng_ust_jni_ctx_entry);
for (i = 0; i < len; i++) {
- if (strcmp(ctx_array[i].context_name, ctx_name) == 0)
- return &ctx_array[i];
+ int32_t offset = ctx_entries_array[i].context_name_offset;
+ const char *string = get_ctx_string_at_offset(offset);
+
+ if (string && strcmp(string, ctx_name) == 0) {
+ return &ctx_entries_array[i];
+ }
}
return NULL;
-
}
-static size_t get_size_cb(struct lttng_ctx_field *field, size_t offset)
+static size_t get_size_cb(struct lttng_ust_ctx_field *field, size_t offset)
{
- struct lttng_ust_jni_ctx *jctx;
+ struct lttng_ust_jni_ctx_entry *jctx;
size_t size = 0;
- const char *ctx_name = field->event_field.name;
+ const char *ctx_name = field->event_field->name;
enum lttng_ust_jni_type jni_type;
+
size += lib_ring_buffer_align(offset, lttng_alignof(char));
size += sizeof(char); /* tag */
jctx = lookup_ctx_by_name(ctx_name);
size += sizeof(char); /* variant */
break;
case JNI_TYPE_STRING:
- size += strlen(jctx->value._string) + 1;
+ {
+ /* The value is an offset, the string is in the "strings" array */
+ int32_t string_offset = jctx->value._string_offset;
+ const char *string = get_ctx_string_at_offset(string_offset);
+
+ if (string) {
+ size += strlen(string) + 1;
+ }
break;
+ }
default:
abort();
}
}
-static void record_cb(struct lttng_ctx_field *field,
+static void record_cb(struct lttng_ust_ctx_field *field,
struct lttng_ust_lib_ring_buffer_ctx *ctx,
- struct lttng_channel *chan)
+ struct lttng_ust_channel_buffer *lttng_chan_buf)
{
- struct lttng_ust_jni_ctx *jctx;
- const char *ctx_name = field->event_field.name;
+ struct lttng_ust_jni_ctx_entry *jctx;
+ const char *ctx_name = field->event_field->name;
enum lttng_ust_jni_type jni_type;
char sel_char;
case JNI_TYPE_NULL:
sel_char = LTTNG_UST_DYNAMIC_TYPE_NONE;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
break;
case JNI_TYPE_INTEGER:
{
sel_char = LTTNG_UST_DYNAMIC_TYPE_S32;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_LONG:
sel_char = LTTNG_UST_DYNAMIC_TYPE_S64;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_DOUBLE:
sel_char = LTTNG_UST_DYNAMIC_TYPE_DOUBLE;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_FLOAT:
sel_char = LTTNG_UST_DYNAMIC_TYPE_FLOAT;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_SHORT:
sel_char = LTTNG_UST_DYNAMIC_TYPE_S16;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_BYTE:
sel_char = LTTNG_UST_DYNAMIC_TYPE_S8;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_BOOLEAN:
sel_char = LTTNG_UST_DYNAMIC_TYPE_S8;
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
lib_ring_buffer_align_ctx(ctx, lttng_alignof(v));
- chan->ops->event_write(ctx, &v, sizeof(v));
+ lttng_chan_buf->ops->event_write(ctx, &v, sizeof(v));
break;
}
case JNI_TYPE_STRING:
{
- const char *str = jctx->value._string;
-
- sel_char = LTTNG_UST_DYNAMIC_TYPE_STRING;
+ int32_t offset = jctx->value._string_offset;
+ const char *str = get_ctx_string_at_offset(offset);
+
+ if (str) {
+ sel_char = LTTNG_UST_DYNAMIC_TYPE_STRING;
+ } else {
+ sel_char = LTTNG_UST_DYNAMIC_TYPE_NONE;
+ }
lib_ring_buffer_align_ctx(ctx, lttng_alignof(char));
- chan->ops->event_write(ctx, &sel_char, sizeof(sel_char));
- chan->ops->event_write(ctx, str, strlen(str) + 1);
+ lttng_chan_buf->ops->event_write(ctx, &sel_char, sizeof(sel_char));
+ if (str) {
+ lttng_chan_buf->ops->event_write(ctx, str, strlen(str) + 1);
+ }
break;
}
default:
}
}
-static void get_value_cb(struct lttng_ctx_field *field,
- struct lttng_ctx_value *value)
+static void get_value_cb(struct lttng_ust_ctx_field *field,
+ struct lttng_ust_ctx_value *value)
{
- struct lttng_ust_jni_ctx *jctx;
- const char *ctx_name = field->event_field.name;
+ struct lttng_ust_jni_ctx_entry *jctx;
+ const char *ctx_name = field->event_field->name;
enum lttng_ust_jni_type jni_type;
jctx = lookup_ctx_by_name(ctx_name);
value->u.s64 = (int64_t) jctx->value._boolean;
break;
case JNI_TYPE_STRING:
- value->sel = LTTNG_UST_DYNAMIC_TYPE_STRING;
- value->u.str = jctx->value._string;
+ {
+ int32_t offset = jctx->value._string_offset;
+ const char *str = get_ctx_string_at_offset(offset);
+
+ if (str) {
+ value->sel = LTTNG_UST_DYNAMIC_TYPE_STRING;
+ value->u.str = str;
+ } else {
+ value->sel = LTTNG_UST_DYNAMIC_TYPE_NONE;
+ }
break;
+ }
default:
abort();
}
if (!provider) {
goto error_provider;
}
+ provider->struct_size = sizeof(*provider);
provider->name = provider_name_cstr;
provider->get_size = get_size_cb;
provider->record = record_cb;
goto error_register;
}
- provider_ref = (jlong) provider;
+ provider_ref = (jlong) (long) provider;
return provider_ref;
/* Error handling. */