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
25 #include <babeltrace2/babeltrace.h>
27 #include "common/common.h"
28 #include "common/assert.h"
29 #include "compat/glib.h"
33 #include "obj-lifetime-mgmt.h"
36 void trace_class_destruction_listener(const bt_trace_class
*tc
, void *data
)
38 struct details_comp
*details_comp
= data
;
40 BT_ASSERT(details_comp
);
41 BT_ASSERT(details_comp
->meta
);
43 /* Remove from hash table, which also destroys the value */
44 g_hash_table_remove(details_comp
->meta
, tc
);
48 struct details_trace_class_meta
*borrow_trace_class_meta(
49 struct details_write_ctx
*ctx
, const bt_trace_class
*tc
)
51 struct details_trace_class_meta
*details_tc_meta
;
53 BT_ASSERT_DBG(ctx
->details_comp
->cfg
.with_meta
);
54 BT_ASSERT_DBG(ctx
->details_comp
->meta
);
55 details_tc_meta
= g_hash_table_lookup(ctx
->details_comp
->meta
, tc
);
56 if (!details_tc_meta
) {
57 /* Not found: create one */
58 details_tc_meta
= details_create_details_trace_class_meta();
59 if (!details_tc_meta
) {
63 /* Register trace class destruction listener */
64 if (bt_trace_class_add_destruction_listener(tc
,
65 trace_class_destruction_listener
,
67 &details_tc_meta
->tc_destruction_listener_id
)) {
71 /* Insert into hash table (becomes the owner) */
72 g_hash_table_insert(ctx
->details_comp
->meta
, (void *) tc
,
79 details_destroy_details_trace_class_meta(details_tc_meta
);
80 details_tc_meta
= NULL
;
83 return details_tc_meta
;
87 bool details_need_to_write_meta_object(struct details_write_ctx
*ctx
,
88 const bt_trace_class
*tc
, const void *obj
)
91 struct details_trace_class_meta
*details_tc_meta
;
93 if (!ctx
->details_comp
->cfg
.with_meta
) {
94 need_to_write
= false;
98 BT_ASSERT_DBG(ctx
->details_comp
->meta
);
99 details_tc_meta
= g_hash_table_lookup(ctx
->details_comp
->meta
, tc
);
100 BT_ASSERT_DBG(details_tc_meta
);
102 !g_hash_table_lookup(details_tc_meta
->objects
, obj
);
105 return need_to_write
;
109 void details_did_write_meta_object(struct details_write_ctx
*ctx
,
110 const bt_trace_class
*tc
, const void *obj
)
112 struct details_trace_class_meta
*details_tc_meta
;
114 BT_ASSERT(ctx
->details_comp
->cfg
.with_meta
);
115 details_tc_meta
= borrow_trace_class_meta(ctx
, tc
);
116 BT_ASSERT(details_tc_meta
);
117 g_hash_table_insert(details_tc_meta
->objects
, (gpointer
) obj
,
118 GUINT_TO_POINTER(1));
122 bool details_need_to_write_trace_class(struct details_write_ctx
*ctx
,
123 const bt_trace_class
*tc
)
125 struct details_trace_class_meta
*details_tc_meta
;
128 if (!ctx
->details_comp
->cfg
.with_meta
) {
129 need_to_write
= false;
133 BT_ASSERT_DBG(ctx
->details_comp
->meta
);
134 details_tc_meta
= g_hash_table_lookup(ctx
->details_comp
->meta
, tc
);
135 need_to_write
= !details_tc_meta
;
138 return need_to_write
;
142 int details_did_write_trace_class(struct details_write_ctx
*ctx
,
143 const bt_trace_class
*tc
)
146 struct details_trace_class_meta
*details_tc_meta
;
148 BT_ASSERT(ctx
->details_comp
->cfg
.with_meta
);
150 /* borrow_trace_class_meta() creates an entry if none exists */
151 details_tc_meta
= borrow_trace_class_meta(ctx
, tc
);
152 if (!details_tc_meta
) {
160 void trace_destruction_listener(const bt_trace
*trace
, void *data
)
162 struct details_comp
*details_comp
= data
;
164 BT_ASSERT(details_comp
);
165 BT_ASSERT(details_comp
->traces
);
167 /* Remove from hash table, which also destroys the value */
168 g_hash_table_remove(details_comp
->traces
, trace
);
172 struct details_trace
*create_details_trace(uint64_t unique_id
)
174 struct details_trace
*details_trace
= g_new0(struct details_trace
, 1);
176 if (!details_trace
) {
180 details_trace
->unique_id
= unique_id
;
181 details_trace
->trace_destruction_listener_id
= UINT64_C(-1);
184 return details_trace
;
189 int details_trace_unique_id(struct details_write_ctx
*ctx
,
190 const bt_trace
*trace
, uint64_t *unique_id
)
193 struct details_trace
*details_trace
= NULL
;
195 BT_ASSERT_DBG(unique_id
);
196 BT_ASSERT_DBG(ctx
->details_comp
->traces
);
197 if (!bt_g_hash_table_contains(ctx
->details_comp
->traces
,
199 /* Not found: create one */
200 *unique_id
= ctx
->details_comp
->next_unique_trace_id
;
201 details_trace
= create_details_trace(*unique_id
);
202 if (!details_trace
) {
206 ctx
->details_comp
->next_unique_trace_id
++;
208 /* Register trace destruction listener if there's none */
209 if (bt_trace_add_destruction_listener(trace
,
210 trace_destruction_listener
,
212 &details_trace
->trace_destruction_listener_id
)) {
216 BT_ASSERT(details_trace
->trace_destruction_listener_id
!=
219 /* Move to hash table */
220 g_hash_table_insert(ctx
->details_comp
->traces
, (gpointer
) trace
,
222 details_trace
= NULL
;
225 details_trace
= g_hash_table_lookup(
226 ctx
->details_comp
->traces
, trace
);
227 *unique_id
= details_trace
->unique_id
;
228 details_trace
= NULL
;
237 g_free(details_trace
);