2 * Copyright (C) 2016 - EfficiOS Inc., Alexandre Montplaisir <alexmonthy@efficios.com>
3 * 2016 - EfficiOS Inc., Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; only
8 * version 2.1 of the License.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "org_lttng_ust_agent_context_LttngContextApi.h"
24 #include <lttng/ust-events.h>
25 #include <lttng/ringbuffer-config.h>
26 #include <lttng/ust-context-provider.h>
29 #include "lttng_ust_context.h"
31 #define LTTNG_UST_JNI_CONTEXT_NAME_LEN 256
32 /* TODO: the value should be variable length. */
33 #define LTTNG_UST_JNI_VALUE_LEN 256
35 enum lttng_ust_jni_type
{
47 struct lttng_ust_jni_ctx
{
48 char context_name
[LTTNG_UST_JNI_CONTEXT_NAME_LEN
];
49 char type
; /* enum lttng_ust_jni_type */
58 char _string
[LTTNG_UST_JNI_VALUE_LEN
];
60 } __attribute__((packed
));
62 /* TLS passing context info from JNI to callbacks. */
63 __thread
struct lttng_ust_jni_tls lttng_ust_context_info_tls
;
65 static struct lttng_ust_jni_ctx
*lookup_ctx_by_name(const char *ctx_name
)
67 struct lttng_ust_jni_ctx
*ctx_array
= lttng_ust_context_info_tls
.ctx
;
68 int i
, len
= lttng_ust_context_info_tls
.len
/ sizeof(struct lttng_ust_jni_ctx
);
70 for (i
= 0; i
< len
; i
++) {
71 if (strcmp(ctx_array
[i
].context_name
, ctx_name
) == 0)
78 static size_t get_size_cb(struct lttng_ctx_field
*field
, size_t offset
)
80 struct lttng_ust_jni_ctx
*jctx
;
82 const char *ctx_name
= field
->event_field
.name
;
83 enum lttng_ust_jni_type jni_type
;
85 size
+= lib_ring_buffer_align(offset
, lttng_alignof(char));
86 size
+= sizeof(char); /* tag */
87 jctx
= lookup_ctx_by_name(ctx_name
);
89 jni_type
= JNI_TYPE_NULL
;
91 jni_type
= jctx
->type
;
96 case JNI_TYPE_INTEGER
:
97 size
+= lib_ring_buffer_align(offset
, lttng_alignof(int32_t));
98 size
+= sizeof(int32_t); /* variant */
101 size
+= lib_ring_buffer_align(offset
, lttng_alignof(int64_t));
102 size
+= sizeof(int64_t); /* variant */
104 case JNI_TYPE_DOUBLE
:
105 size
+= lib_ring_buffer_align(offset
, lttng_alignof(double));
106 size
+= sizeof(double); /* variant */
109 size
+= lib_ring_buffer_align(offset
, lttng_alignof(float));
110 size
+= sizeof(float); /* variant */
113 size
+= lib_ring_buffer_align(offset
, lttng_alignof(int16_t));
114 size
+= sizeof(int16_t); /* variant */
116 case JNI_TYPE_BYTE
: /* Fall-through. */
117 case JNI_TYPE_BOOLEAN
:
118 size
+= lib_ring_buffer_align(offset
, lttng_alignof(char));
119 size
+= sizeof(char); /* variant */
121 case JNI_TYPE_STRING
:
122 size
+= strlen(jctx
->value
._string
) + 1;
131 static void record_cb(struct lttng_ctx_field
*field
,
132 struct lttng_ust_lib_ring_buffer_ctx
*ctx
,
133 struct lttng_channel
*chan
)
135 struct lttng_ust_jni_ctx
*jctx
;
136 const char *ctx_name
= field
->event_field
.name
;
137 enum lttng_ust_jni_type jni_type
;
140 jctx
= lookup_ctx_by_name(ctx_name
);
142 jni_type
= JNI_TYPE_NULL
;
144 jni_type
= jctx
->type
;
149 sel_char
= LTTNG_UST_DYNAMIC_TYPE_NONE
;
150 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
151 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
153 case JNI_TYPE_INTEGER
:
155 int32_t v
= jctx
->value
._integer
;
157 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S32
;
158 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
159 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
160 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
161 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
166 int64_t v
= jctx
->value
._long
;
168 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S64
;
169 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
170 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
171 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
172 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
175 case JNI_TYPE_DOUBLE
:
177 double v
= jctx
->value
._double
;
179 sel_char
= LTTNG_UST_DYNAMIC_TYPE_DOUBLE
;
180 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
181 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
182 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
183 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
188 float v
= jctx
->value
._float
;
190 sel_char
= LTTNG_UST_DYNAMIC_TYPE_FLOAT
;
191 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
192 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
193 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
194 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
199 int16_t v
= jctx
->value
._short
;
201 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S16
;
202 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
203 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
204 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
205 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
210 char v
= jctx
->value
._byte
;
212 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S8
;
213 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
214 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
215 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
216 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
219 case JNI_TYPE_BOOLEAN
:
221 char v
= jctx
->value
._boolean
;
223 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S8
;
224 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
225 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
226 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(v
));
227 chan
->ops
->event_write(ctx
, &v
, sizeof(v
));
230 case JNI_TYPE_STRING
:
232 const char *str
= jctx
->value
._string
;
234 sel_char
= LTTNG_UST_DYNAMIC_TYPE_STRING
;
235 lib_ring_buffer_align_ctx(ctx
, lttng_alignof(char));
236 chan
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
237 chan
->ops
->event_write(ctx
, str
, strlen(str
) + 1);
245 static void get_value_cb(struct lttng_ctx_field
*field
,
246 struct lttng_ctx_value
*value
)
248 struct lttng_ust_jni_ctx
*jctx
;
249 const char *ctx_name
= field
->event_field
.name
;
250 enum lttng_ust_jni_type jni_type
;
252 jctx
= lookup_ctx_by_name(ctx_name
);
254 jni_type
= JNI_TYPE_NULL
;
256 jni_type
= jctx
->type
;
261 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_NONE
;
263 case JNI_TYPE_INTEGER
:
264 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
265 value
->u
.s64
= (int64_t) jctx
->value
._integer
;
268 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
269 value
->u
.s64
= jctx
->value
._long
;
271 case JNI_TYPE_DOUBLE
:
272 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_DOUBLE
;
273 value
->u
.d
= jctx
->value
._double
;
276 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_DOUBLE
;
277 value
->u
.d
= (double) jctx
->value
._float
;
280 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
281 value
->u
.s64
= (int64_t) jctx
->value
._short
;
284 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
285 value
->u
.s64
= (int64_t) jctx
->value
._byte
;
287 case JNI_TYPE_BOOLEAN
:
288 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
289 value
->u
.s64
= (int64_t) jctx
->value
._boolean
;
291 case JNI_TYPE_STRING
:
292 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_STRING
;
293 value
->u
.str
= jctx
->value
._string
;
301 * Register a context provider to UST.
303 * Called from the Java side when an application registers a context retriever,
304 * so we create and register a corresponding provider on the C side.
306 JNIEXPORT jlong JNICALL
Java_org_lttng_ust_agent_context_LttngContextApi_registerProvider(JNIEnv
*env
,
308 jstring provider_name
)
311 const char *provider_name_jstr
;
312 char *provider_name_cstr
;
313 struct lttng_ust_context_provider
*provider
;
315 * Note: a "jlong" is 8 bytes on all architectures, whereas a
320 provider_name_jstr
= (*env
)->GetStringUTFChars(env
, provider_name
, &iscopy
);
321 if (!provider_name_jstr
) {
324 /* Keep our own copy of the string so UST can use it. */
325 provider_name_cstr
= strdup(provider_name_jstr
);
326 (*env
)->ReleaseStringUTFChars(env
, provider_name
, provider_name_jstr
);
327 if (!provider_name_cstr
) {
330 provider
= zmalloc(sizeof(*provider
));
334 provider
->name
= provider_name_cstr
;
335 provider
->get_size
= get_size_cb
;
336 provider
->record
= record_cb
;
337 provider
->get_value
= get_value_cb
;
339 if (lttng_ust_context_provider_register(provider
)) {
343 provider_ref
= (jlong
) provider
;
346 /* Error handling. */
350 free(provider_name_cstr
);
357 * Unregister a previously-registered context provider.
359 * Called from the Java side when an application unregisters a context retriever,
360 * so we unregister and delete the corresponding provider on the C side.
362 JNIEXPORT
void JNICALL
Java_org_lttng_ust_agent_context_LttngContextApi_unregisterProvider(JNIEnv
*env
,
366 struct lttng_ust_context_provider
*provider
=
367 (struct lttng_ust_context_provider
*) (unsigned long) provider_ref
;
373 lttng_ust_context_provider_unregister(provider
);
375 free(provider
->name
);