2 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include <babeltrace2/babeltrace.h>
25 #include "common/common.h"
26 #include "common/assert.h"
27 #include "compat/glib.h"
31 #include "obj-lifetime-mgmt.h"
34 void trace_class_destruction_listener(const bt_trace_class
*tc
, void *data
)
36 struct details_comp
*details_comp
= data
;
38 BT_ASSERT(details_comp
);
39 BT_ASSERT(details_comp
->meta
);
41 /* Remove from hash table, which also destroys the value */
42 g_hash_table_remove(details_comp
->meta
, tc
);
46 struct details_trace_class_meta
*borrow_trace_class_meta(
47 struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
49 struct details_trace_class_meta
*details_tc_meta
;
51 BT_ASSERT(ctx
->details_comp
->cfg
.with_meta
);
52 BT_ASSERT(ctx
->details_comp
->meta
);
53 details_tc_meta
= g_hash_table_lookup(ctx
->details_comp
->meta
, tc
);
54 if (!details_tc_meta
) {
55 /* Not found: create one */
56 details_tc_meta
= details_create_details_trace_class_meta();
57 if (!details_tc_meta
) {
61 /* Register trace class destruction listener */
62 if (bt_trace_class_add_destruction_listener(tc
,
63 trace_class_destruction_listener
,
65 &details_tc_meta
->tc_destruction_listener_id
)) {
69 /* Insert into hash table (becomes the owner) */
70 g_hash_table_insert(ctx
->details_comp
->meta
, (void *) tc
,
77 details_destroy_details_trace_class_meta(details_tc_meta
);
78 details_tc_meta
= NULL
;
81 return details_tc_meta
;
85 bool details_need_to_write_meta_object(struct details_write_ctx
*ctx
,
86 const bt_trace_class
*tc
, const void *obj
)
89 struct details_trace_class_meta
*details_tc_meta
;
91 if (!ctx
->details_comp
->cfg
.with_meta
) {
92 need_to_write
= false;
96 BT_ASSERT(ctx
->details_comp
->meta
);
97 details_tc_meta
= g_hash_table_lookup(ctx
->details_comp
->meta
, tc
);
98 BT_ASSERT(details_tc_meta
);
100 !g_hash_table_lookup(details_tc_meta
->objects
, obj
);
103 return need_to_write
;
107 void details_did_write_meta_object(struct details_write_ctx
*ctx
,
108 const bt_trace_class
*tc
, const void *obj
)
110 struct details_trace_class_meta
*details_tc_meta
;
112 BT_ASSERT(ctx
->details_comp
->cfg
.with_meta
);
113 details_tc_meta
= borrow_trace_class_meta(ctx
, tc
);
114 BT_ASSERT(details_tc_meta
);
115 g_hash_table_insert(details_tc_meta
->objects
, (gpointer
) obj
,
116 GUINT_TO_POINTER(1));
120 bool details_need_to_write_trace_class(struct details_write_ctx
*ctx
,
121 const bt_trace_class
*tc
)
123 struct details_trace_class_meta
*details_tc_meta
;
126 if (!ctx
->details_comp
->cfg
.with_meta
) {
127 need_to_write
= false;
131 BT_ASSERT(ctx
->details_comp
->meta
);
132 details_tc_meta
= g_hash_table_lookup(ctx
->details_comp
->meta
, tc
);
133 need_to_write
= !details_tc_meta
;
136 return need_to_write
;
140 int details_did_write_trace_class(struct details_write_ctx
*ctx
,
141 const bt_trace_class
*tc
)
144 struct details_trace_class_meta
*details_tc_meta
;
146 BT_ASSERT(ctx
->details_comp
->cfg
.with_meta
);
148 /* borrow_trace_class_meta() creates an entry if none exists */
149 details_tc_meta
= borrow_trace_class_meta(ctx
, tc
);
150 if (!details_tc_meta
) {
158 void trace_destruction_listener(const bt_trace
*trace
, void *data
)
160 struct details_comp
*details_comp
= data
;
162 BT_ASSERT(details_comp
);
163 BT_ASSERT(details_comp
->traces
);
165 /* Remove from hash table, which also destroys the value */
166 g_hash_table_remove(details_comp
->traces
, trace
);
170 struct details_trace
*create_details_trace(uint64_t unique_id
)
172 struct details_trace
*details_trace
= g_new0(struct details_trace
, 1);
174 if (!details_trace
) {
178 details_trace
->unique_id
= unique_id
;
179 details_trace
->trace_destruction_listener_id
= UINT64_C(-1);
182 return details_trace
;
187 int details_trace_unique_id(struct details_write_ctx
*ctx
,
188 const bt_trace
*trace
, uint64_t *unique_id
)
191 struct details_trace
*details_trace
= NULL
;
193 BT_ASSERT(unique_id
);
194 BT_ASSERT(ctx
->details_comp
->traces
);
195 if (!bt_g_hash_table_contains(ctx
->details_comp
->traces
,
197 /* Not found: create one */
198 *unique_id
= ctx
->details_comp
->next_unique_trace_id
;
199 details_trace
= create_details_trace(*unique_id
);
200 if (!details_trace
) {
204 ctx
->details_comp
->next_unique_trace_id
++;
206 /* Register trace destruction listener if there's none */
207 if (bt_trace_add_destruction_listener(trace
,
208 trace_destruction_listener
,
210 &details_trace
->trace_destruction_listener_id
)) {
214 BT_ASSERT(details_trace
->trace_destruction_listener_id
!=
217 /* Move to hash table */
218 g_hash_table_insert(ctx
->details_comp
->traces
, (gpointer
) trace
,
220 details_trace
= NULL
;
223 details_trace
= g_hash_table_lookup(
224 ctx
->details_comp
->traces
, trace
);
225 *unique_id
= details_trace
->unique_id
;
226 details_trace
= NULL
;
235 g_free(details_trace
);