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