c8dd848b1dfafe49778ecdeba6c3dcd0b5c81ed5
[lttng-tools.git] / ltt-sessiond / ust-app.c
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
6 * as published by the Free Software Foundation; only version 2
7 * of the License.
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>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include <lttngerr.h>
28
29 #include "hashtable.h"
30 #include "ust-app.h"
31 #include "../hashtable/hash.h"
32
33 /*
34 * Delete a traceable application structure from the global list.
35 */
36 static void delete_ust_app(struct ust_app *lta)
37 {
38 int ret;
39 struct cds_lfht_node *node;
40 struct cds_lfht_iter iter;
41
42 rcu_read_lock();
43
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);
52 }
53
54 free(lta->channels);
55 close(lta->key.sock);
56
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);
69 }
70 }
71
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();
91 }
92
93 /*
94 * URCU intermediate call to delete an UST app.
95 */
96 static void delete_ust_app_rcu(struct rcu_head *head)
97 {
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);
104 }
105
106 /*
107 * Find an ust_app using the sock and return it.
108 */
109 static struct ust_app *find_app_by_sock(int sock)
110 {
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
139 error:
140 return NULL;
141 }
142
143 /*
144 * Return pointer to traceable apps list.
145 */
146 struct cds_lfht *ust_app_get_ht(void)
147 {
148 return ust_app_ht;
149 }
150
151 /*
152 * Return ust app pointer or NULL if not found.
153 */
154 struct ust_app *ust_app_find_by_pid(pid_t pid)
155 {
156 struct cds_lfht_node *node;
157 struct cds_lfht_iter iter;
158
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;
166 }
167 rcu_read_unlock();
168
169 DBG2("Found UST app by pid %d", pid);
170
171 return caa_container_of(node, struct ust_app, node);
172
173 error:
174 return NULL;
175 }
176
177 /*
178 * Using pid and uid (of the app), allocate a new ust_app struct and
179 * add it to the global traceable app list.
180 *
181 * On success, return 0, else return malloc ENOMEM.
182 */
183 int ust_app_register(struct ust_register_msg *msg, int sock)
184 {
185 struct ust_app *lta;
186
187 lta = malloc(sizeof(struct ust_app));
188 if (lta == NULL) {
189 perror("malloc");
190 return -ENOMEM;
191 }
192
193 lta->uid = msg->uid;
194 lta->gid = msg->gid;
195 lta->key.pid = msg->pid;
196 lta->ppid = msg->ppid;
197 lta->v_major = msg->major;
198 lta->v_minor = msg->minor;
199 lta->key.sock = sock;
200 strncpy(lta->name, msg->name, sizeof(lta->name));
201 lta->name[16] = '\0';
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 *));
209
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();
214
215 DBG("App registered with pid:%d ppid:%d uid:%d gid:%d sock:%d name:%s"
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);
218
219 return 0;
220 }
221
222 /*
223 * Unregister app by removing it from the global traceable app list and freeing
224 * the data struct.
225 *
226 * The socket is already closed at this point so no close to sock.
227 */
228 void ust_app_unregister(int sock)
229 {
230 struct ust_app *lta;
231
232 DBG2("UST app unregistering sock %d", sock);
233
234 lta = find_app_by_sock(sock);
235 if (lta) {
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);
239 }
240 }
241
242 /*
243 * Return traceable_app_count
244 */
245 unsigned long ust_app_list_count(void)
246 {
247 unsigned long count;
248
249 rcu_read_lock();
250 count = hashtable_get_count(ust_app_ht);
251 rcu_read_unlock();
252
253 return count;
254 }
255
256 /*
257 * Free and clean all traceable apps of the global list.
258 */
259 void ust_app_clean_list(void)
260 {
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);
276 }
277
278 rcu_read_unlock();
279 }
280
281 /*
282 * Init UST app hash table.
283 */
284 void ust_app_ht_alloc(void)
285 {
286 ust_app_ht = hashtable_new(0);
287 ust_app_sock_key_map = hashtable_new(0);
288 }
This page took 0.03493 seconds and 3 git commands to generate.