Basic hashtable support for UST
[lttng-tools.git] / ltt-sessiond / ust-app.c
CommitLineData
91d76f53
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
82a3637f
DG
6 * as published by the Free Software Foundation; only version 2
7 * of the License.
91d76f53
DG
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#define _GNU_SOURCE
20#include <errno.h>
21#include <pthread.h>
22#include <stdio.h>
23#include <stdlib.h>
099e26bd
DG
24#include <string.h>
25#include <unistd.h>
91d76f53 26
1e307fab
DG
27#include <lttngerr.h>
28
f6a9efaa 29#include "hashtable.h"
56fff090 30#include "ust-app.h"
f6a9efaa 31#include "../hashtable/hash.h"
91d76f53
DG
32
33/*
099e26bd 34 * Delete a traceable application structure from the global list.
91d76f53 35 */
f6a9efaa 36static void delete_ust_app(struct ust_app *lta)
91d76f53 37{
f6a9efaa
DG
38 int ret;
39 struct cds_lfht_node *node;
40 struct cds_lfht_iter iter;
44d3bd01 41
f6a9efaa 42 rcu_read_lock();
44d3bd01 43
f6a9efaa
DG
44 hashtable_get_first(lta->channels, &iter);
45 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
46 ret = hashtable_del(lta->channels, &iter);
47 if (!ret) {
48 trace_ust_destroy_channel(
49 caa_container_of(node, struct ltt_ust_channel, node));
50 }
51 hashtable_get_next(lta->channels, &iter);
44d3bd01 52 }
099e26bd 53
f6a9efaa
DG
54 free(lta->channels);
55 close(lta->key.sock);
56fff090 56
f6a9efaa
DG
57 /* Remove from apps hash table */
58 node = hashtable_lookup(ust_app_ht,
59 (void *) ((unsigned long) lta->key.pid), sizeof(void *), &iter);
60 if (node == NULL) {
61 ERR("UST app pid %d not found in hash table", lta->key.pid);
62 } else {
63 ret = hashtable_del(ust_app_ht, &iter);
64 if (ret) {
65 ERR("UST app unable to delete app %d from hash table",
66 lta->key.pid);
67 } else {
68 DBG2("UST app pid %d deleted", lta->key.pid);
56fff090
DG
69 }
70 }
71
f6a9efaa
DG
72 /* Remove from key hash table */
73 node = hashtable_lookup(ust_app_sock_key_map,
74 (void *) ((unsigned long) lta->key.sock), sizeof(void *), &iter);
75 if (node == NULL) {
76 ERR("UST app key %d not found in key hash table", lta->key.sock);
77 } else {
78 ret = hashtable_del(ust_app_sock_key_map, &iter);
79 if (ret) {
80 ERR("UST app unable to delete app sock %d from key hash table",
81 lta->key.sock);
82 } else {
83 DBG2("UST app pair sock %d key %d deleted",
84 lta->key.sock, lta->key.pid);
85 }
86 }
87
88 free(lta);
89
90 rcu_read_unlock();
099e26bd
DG
91}
92
93/*
f6a9efaa 94 * URCU intermediate call to delete an UST app.
099e26bd 95 */
f6a9efaa 96static void delete_ust_app_rcu(struct rcu_head *head)
099e26bd 97{
f6a9efaa
DG
98 struct cds_lfht_node *node =
99 caa_container_of(head, struct cds_lfht_node, head);
100 struct ust_app *app =
101 caa_container_of(node, struct ust_app, node);
102
103 delete_ust_app(app);
099e26bd
DG
104}
105
106/*
f6a9efaa 107 * Find an ust_app using the sock and return it.
099e26bd 108 */
f6a9efaa 109static struct ust_app *find_app_by_sock(int sock)
099e26bd 110{
f6a9efaa
DG
111 struct cds_lfht_node *node;
112 struct ust_app_key *key;
113 struct cds_lfht_iter iter;
114 //struct ust_app *app;
115
116 rcu_read_lock();
117
118 node = hashtable_lookup(ust_app_sock_key_map,
119 (void *)((unsigned long) sock), sizeof(void *), &iter);
120 if (node == NULL) {
121 DBG2("UST app find by sock %d key not found", sock);
122 rcu_read_unlock();
123 goto error;
124 }
125
126 key = caa_container_of(node, struct ust_app_key, node);
127
128 node = hashtable_lookup(ust_app_ht,
129 (void *)((unsigned long) key->pid), sizeof(void *), &iter);
130 if (node == NULL) {
131 DBG2("UST app find by sock %d not found", sock);
132 rcu_read_unlock();
133 goto error;
134 }
135 rcu_read_unlock();
136
137 return caa_container_of(node, struct ust_app, node);
138
139error:
140 return NULL;
099e26bd
DG
141}
142
143/*
f6a9efaa 144 * Return pointer to traceable apps list.
099e26bd 145 */
f6a9efaa 146struct cds_lfht *ust_app_get_ht(void)
099e26bd 147{
f6a9efaa 148 return ust_app_ht;
91d76f53
DG
149}
150
0177d773 151/*
f6a9efaa 152 * Return ust app pointer or NULL if not found.
0177d773 153 */
f6a9efaa 154struct ust_app *ust_app_find_by_pid(pid_t pid)
0177d773 155{
f6a9efaa
DG
156 struct cds_lfht_node *node;
157 struct cds_lfht_iter iter;
0177d773 158
f6a9efaa
DG
159 rcu_read_lock();
160 node = hashtable_lookup(ust_app_ht,
161 (void *)((unsigned long) pid), sizeof(void *), &iter);
162 if (node == NULL) {
163 rcu_read_unlock();
164 DBG2("UST app no found with pid %d", pid);
165 goto error;
0177d773 166 }
f6a9efaa 167 rcu_read_unlock();
0177d773 168
f6a9efaa 169 DBG2("Found UST app by pid %d", pid);
44d3bd01 170
f6a9efaa
DG
171 return caa_container_of(node, struct ust_app, node);
172
173error:
0177d773
DG
174 return NULL;
175}
176
91d76f53 177/*
56fff090 178 * Using pid and uid (of the app), allocate a new ust_app struct and
050349bb 179 * add it to the global traceable app list.
91d76f53 180 *
050349bb 181 * On success, return 0, else return malloc ENOMEM.
91d76f53 182 */
56fff090 183int ust_app_register(struct ust_register_msg *msg, int sock)
91d76f53 184{
56fff090 185 struct ust_app *lta;
91d76f53 186
56fff090 187 lta = malloc(sizeof(struct ust_app));
91d76f53
DG
188 if (lta == NULL) {
189 perror("malloc");
190 return -ENOMEM;
191 }
192
099e26bd
DG
193 lta->uid = msg->uid;
194 lta->gid = msg->gid;
f6a9efaa 195 lta->key.pid = msg->pid;
099e26bd
DG
196 lta->ppid = msg->ppid;
197 lta->v_major = msg->major;
198 lta->v_minor = msg->minor;
f6a9efaa 199 lta->key.sock = sock;
099e26bd
DG
200 strncpy(lta->name, msg->name, sizeof(lta->name));
201 lta->name[16] = '\0';
f6a9efaa
DG
202 hashtable_node_init(&lta->node, (void *)((unsigned long)lta->key.pid),
203 sizeof(void *));
204 lta->channels = hashtable_new_str(0);
205
206 /* Set sock key map */
207 hashtable_node_init(&lta->key.node, (void *)((unsigned long)lta->key.sock),
208 sizeof(void *));
099e26bd 209
f6a9efaa
DG
210 rcu_read_lock();
211 hashtable_add_unique(ust_app_ht, &lta->node);
212 hashtable_add_unique(ust_app_sock_key_map, &lta->key.node);
213 rcu_read_unlock();
099e26bd
DG
214
215 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
f6a9efaa
DG
216 " (version %d.%d)", lta->key.pid, lta->ppid, lta->uid, lta->gid,
217 lta->key.sock, lta->name, lta->v_major, lta->v_minor);
91d76f53
DG
218
219 return 0;
220}
221
222/*
050349bb
DG
223 * Unregister app by removing it from the global traceable app list and freeing
224 * the data struct.
099e26bd
DG
225 *
226 * The socket is already closed at this point so no close to sock.
91d76f53 227 */
56fff090 228void ust_app_unregister(int sock)
91d76f53 229{
56fff090 230 struct ust_app *lta;
91d76f53 231
f6a9efaa
DG
232 DBG2("UST app unregistering sock %d", sock);
233
099e26bd
DG
234 lta = find_app_by_sock(sock);
235 if (lta) {
f6a9efaa
DG
236 DBG("PID %d unregistering with sock %d", lta->key.pid, sock);
237 /* FIXME: Better use a call_rcu here ? */
238 delete_ust_app(lta);
91d76f53
DG
239 }
240}
241
242/*
050349bb 243 * Return traceable_app_count
91d76f53 244 */
f6a9efaa 245unsigned long ust_app_list_count(void)
91d76f53 246{
f6a9efaa 247 unsigned long count;
91d76f53 248
f6a9efaa
DG
249 rcu_read_lock();
250 count = hashtable_get_count(ust_app_ht);
251 rcu_read_unlock();
91d76f53 252
099e26bd 253 return count;
91d76f53
DG
254}
255
256/*
099e26bd 257 * Free and clean all traceable apps of the global list.
91d76f53 258 */
56fff090 259void ust_app_clean_list(void)
91d76f53 260{
f6a9efaa
DG
261 int ret;
262 struct cds_lfht_node *node;
263 struct cds_lfht_iter iter;
264
265 DBG2("UST app clean hash table");
266
267 rcu_read_lock();
268
269 hashtable_get_first(ust_app_ht, &iter);
270 while ((node = hashtable_iter_get_node(&iter)) != NULL) {
271 ret = hashtable_del(ust_app_ht, &iter);
272 if (!ret) {
273 call_rcu(&node->head, delete_ust_app_rcu);
274 }
275 hashtable_get_next(ust_app_ht, &iter);
91d76f53 276 }
f6a9efaa
DG
277
278 rcu_read_unlock();
279}
280
281/*
282 * Init UST app hash table.
283 */
284void ust_app_ht_alloc(void)
285{
286 ust_app_ht = hashtable_new(0);
287 ust_app_sock_key_map = hashtable_new(0);
91d76f53 288}
This page took 0.037719 seconds and 4 git commands to generate.