Move to kernel style SPDX license identifiers
[babeltrace.git] / src / plugins / text / details / obj-lifetime-mgmt.c
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #include <stdbool.h>
8
9 #include <babeltrace2/babeltrace.h>
10
11 #include "common/common.h"
12 #include "common/assert.h"
13 #include "compat/glib.h"
14
15 #include "details.h"
16 #include "write.h"
17 #include "obj-lifetime-mgmt.h"
18
19 static
20 void trace_class_destruction_listener(const bt_trace_class *tc, void *data)
21 {
22 struct details_comp *details_comp = data;
23
24 BT_ASSERT(details_comp);
25 BT_ASSERT(details_comp->meta);
26
27 /* Remove from hash table, which also destroys the value */
28 g_hash_table_remove(details_comp->meta, tc);
29 }
30
31 static
32 struct details_trace_class_meta *borrow_trace_class_meta(
33 struct details_write_ctx *ctx, const bt_trace_class *tc)
34 {
35 struct details_trace_class_meta *details_tc_meta;
36
37 BT_ASSERT_DBG(ctx->details_comp->cfg.with_meta);
38 BT_ASSERT_DBG(ctx->details_comp->meta);
39 details_tc_meta = g_hash_table_lookup(ctx->details_comp->meta, tc);
40 if (!details_tc_meta) {
41 /* Not found: create one */
42 details_tc_meta = details_create_details_trace_class_meta();
43 if (!details_tc_meta) {
44 goto error;
45 }
46
47 /* Register trace class destruction listener */
48 if (bt_trace_class_add_destruction_listener(tc,
49 trace_class_destruction_listener,
50 ctx->details_comp,
51 &details_tc_meta->tc_destruction_listener_id)) {
52 goto error;
53 }
54
55 /* Insert into hash table (becomes the owner) */
56 g_hash_table_insert(ctx->details_comp->meta, (void *) tc,
57 details_tc_meta);
58 }
59
60 goto end;
61
62 error:
63 details_destroy_details_trace_class_meta(details_tc_meta);
64 details_tc_meta = NULL;
65
66 end:
67 return details_tc_meta;
68 }
69
70 BT_HIDDEN
71 bool details_need_to_write_meta_object(struct details_write_ctx *ctx,
72 const bt_trace_class *tc, const void *obj)
73 {
74 bool need_to_write;
75 struct details_trace_class_meta *details_tc_meta;
76
77 if (!ctx->details_comp->cfg.with_meta) {
78 need_to_write = false;
79 goto end;
80 }
81
82 BT_ASSERT_DBG(ctx->details_comp->meta);
83 details_tc_meta = g_hash_table_lookup(ctx->details_comp->meta, tc);
84 BT_ASSERT_DBG(details_tc_meta);
85 need_to_write =
86 !g_hash_table_lookup(details_tc_meta->objects, obj);
87
88 end:
89 return need_to_write;
90 }
91
92 BT_HIDDEN
93 void details_did_write_meta_object(struct details_write_ctx *ctx,
94 const bt_trace_class *tc, const void *obj)
95 {
96 struct details_trace_class_meta *details_tc_meta;
97
98 BT_ASSERT(ctx->details_comp->cfg.with_meta);
99 details_tc_meta = borrow_trace_class_meta(ctx, tc);
100 BT_ASSERT(details_tc_meta);
101 g_hash_table_insert(details_tc_meta->objects, (gpointer) obj,
102 GUINT_TO_POINTER(1));
103 }
104
105 BT_HIDDEN
106 bool details_need_to_write_trace_class(struct details_write_ctx *ctx,
107 const bt_trace_class *tc)
108 {
109 struct details_trace_class_meta *details_tc_meta;
110 bool need_to_write;
111
112 if (!ctx->details_comp->cfg.with_meta) {
113 need_to_write = false;
114 goto end;
115 }
116
117 BT_ASSERT_DBG(ctx->details_comp->meta);
118 details_tc_meta = g_hash_table_lookup(ctx->details_comp->meta, tc);
119 need_to_write = !details_tc_meta;
120
121 end:
122 return need_to_write;
123 }
124
125 BT_HIDDEN
126 int details_did_write_trace_class(struct details_write_ctx *ctx,
127 const bt_trace_class *tc)
128 {
129 int ret = 0;
130 struct details_trace_class_meta *details_tc_meta;
131
132 BT_ASSERT(ctx->details_comp->cfg.with_meta);
133
134 /* borrow_trace_class_meta() creates an entry if none exists */
135 details_tc_meta = borrow_trace_class_meta(ctx, tc);
136 if (!details_tc_meta) {
137 ret = -1;
138 }
139
140 return ret;
141 }
142
143 static
144 void trace_destruction_listener(const bt_trace *trace, void *data)
145 {
146 struct details_comp *details_comp = data;
147
148 BT_ASSERT(details_comp);
149 BT_ASSERT(details_comp->traces);
150
151 /* Remove from hash table, which also destroys the value */
152 g_hash_table_remove(details_comp->traces, trace);
153 }
154
155 static
156 struct details_trace *create_details_trace(uint64_t unique_id)
157 {
158 struct details_trace *details_trace = g_new0(struct details_trace, 1);
159
160 if (!details_trace) {
161 goto end;
162 }
163
164 details_trace->unique_id = unique_id;
165 details_trace->trace_destruction_listener_id = UINT64_C(-1);
166
167 end:
168 return details_trace;
169 }
170
171
172 BT_HIDDEN
173 int details_trace_unique_id(struct details_write_ctx *ctx,
174 const bt_trace *trace, uint64_t *unique_id)
175 {
176 int ret = 0;
177 struct details_trace *details_trace = NULL;
178
179 BT_ASSERT_DBG(unique_id);
180 BT_ASSERT_DBG(ctx->details_comp->traces);
181 if (!bt_g_hash_table_contains(ctx->details_comp->traces,
182 trace)) {
183 /* Not found: create one */
184 *unique_id = ctx->details_comp->next_unique_trace_id;
185 details_trace = create_details_trace(*unique_id);
186 if (!details_trace) {
187 goto error;
188 }
189
190 ctx->details_comp->next_unique_trace_id++;
191
192 /* Register trace destruction listener if there's none */
193 if (bt_trace_add_destruction_listener(trace,
194 trace_destruction_listener,
195 ctx->details_comp,
196 &details_trace->trace_destruction_listener_id)) {
197 goto error;
198 }
199
200 BT_ASSERT(details_trace->trace_destruction_listener_id !=
201 UINT64_C(-1));
202
203 /* Move to hash table */
204 g_hash_table_insert(ctx->details_comp->traces, (gpointer) trace,
205 details_trace);
206 details_trace = NULL;
207 } else {
208 /* Found */
209 details_trace = g_hash_table_lookup(
210 ctx->details_comp->traces, trace);
211 *unique_id = details_trace->unique_id;
212 details_trace = NULL;
213 }
214
215 goto end;
216
217 error:
218 ret = -1;
219
220 end:
221 g_free(details_trace);
222
223 return ret;
224 }
This page took 0.034735 seconds and 4 git commands to generate.