begin support for UST in live, not yet perfect but starting to work
[lttngtop.git] / src / common.c
1 /*
2 * Copyright (C) 2011-2012 Julien Desfossez
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #include <babeltrace/ctf/events.h>
19 #include <stdlib.h>
20 #include <linux/unistd.h>
21 #include <string.h>
22 #include "common.h"
23
24 uint64_t get_cpu_id(const struct bt_ctf_event *event)
25 {
26 const struct bt_definition *scope;
27 uint64_t cpu_id;
28
29 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_PACKET_CONTEXT);
30 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(event, scope, "cpu_id"));
31 if (bt_ctf_field_get_error()) {
32 fprintf(stderr, "[error] get cpu_id\n");
33 return -1ULL;
34 }
35
36 return cpu_id;
37 }
38
39 uint64_t get_context_tid(const struct bt_ctf_event *event)
40 {
41 const struct bt_definition *scope;
42 uint64_t tid;
43
44 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
45 tid = bt_ctf_get_int64(bt_ctf_get_field(event,
46 scope, "_tid"));
47 if (bt_ctf_field_get_error()) {
48 tid = bt_ctf_get_int64(bt_ctf_get_field(event,
49 scope, "_vtid"));
50 if (bt_ctf_field_get_error()) {
51 fprintf(stderr, "Missing tid context info\n");
52 return -1ULL;
53 }
54 }
55
56 return tid;
57 }
58
59 uint64_t get_context_pid(const struct bt_ctf_event *event)
60 {
61 const struct bt_definition *scope;
62 uint64_t pid;
63
64 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
65 pid = bt_ctf_get_int64(bt_ctf_get_field(event,
66 scope, "_pid"));
67 if (bt_ctf_field_get_error()) {
68 /* Try UST pid */
69 pid = bt_ctf_get_int64(bt_ctf_get_field(event,
70 scope, "_vpid"));
71 if (bt_ctf_field_get_error()) {
72 fprintf(stderr, "Missing pid context info\n");
73 return -1ULL;
74 }
75 }
76
77 return pid;
78 }
79
80 uint64_t get_context_ppid(const struct bt_ctf_event *event)
81 {
82 const struct bt_definition *scope;
83 uint64_t ppid;
84
85 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
86 ppid = bt_ctf_get_int64(bt_ctf_get_field(event,
87 scope, "_ppid"));
88 if (bt_ctf_field_get_error()) {
89 return -1ULL;
90 }
91
92 return ppid;
93 }
94
95 uint64_t get_context_vtid(const struct bt_ctf_event *event)
96 {
97 const struct bt_definition *scope;
98 uint64_t vtid;
99
100 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
101 vtid = bt_ctf_get_int64(bt_ctf_get_field(event,
102 scope, "_vtid"));
103 if (bt_ctf_field_get_error()) {
104 return -1ULL;
105 }
106
107 return vtid;
108 }
109
110 uint64_t get_context_vpid(const struct bt_ctf_event *event)
111 {
112 const struct bt_definition *scope;
113 uint64_t vpid;
114
115 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
116 vpid = bt_ctf_get_int64(bt_ctf_get_field(event,
117 scope, "_vpid"));
118 if (bt_ctf_field_get_error()) {
119 return -1ULL;
120 }
121
122 return vpid;
123 }
124
125 uint64_t get_context_vppid(const struct bt_ctf_event *event)
126 {
127 const struct bt_definition *scope;
128 uint64_t vppid;
129
130 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
131 vppid = bt_ctf_get_int64(bt_ctf_get_field(event,
132 scope, "_vppid"));
133 if (bt_ctf_field_get_error()) {
134 return -1ULL;
135 }
136
137 return vppid;
138 }
139
140 char *get_context_comm(const struct bt_ctf_event *event)
141 {
142 const struct bt_definition *scope;
143 char *comm;
144
145 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
146 comm = bt_ctf_get_char_array(bt_ctf_get_field(event,
147 scope, "_procname"));
148 if (bt_ctf_field_get_error()) {
149 fprintf(stderr, "Missing comm context info\n");
150 return NULL;
151 }
152
153 return comm;
154 }
155
156 char *get_context_hostname(const struct bt_ctf_event *event)
157 {
158 const struct bt_definition *scope;
159 char *hostname;
160
161 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
162 hostname = bt_ctf_get_char_array(bt_ctf_get_field(event,
163 scope, "_hostname"));
164 if (bt_ctf_field_get_error()) {
165 return NULL;
166 }
167
168 return hostname;
169 }
170
171 /*
172 * To get the parent process, put the pid in the tid field
173 * because the parent process gets pid = tid
174 */
175 struct processtop *find_process_tid(struct lttngtop *ctx, int tid, const char *comm)
176 {
177 struct processtop *tmp;
178
179 tmp = g_hash_table_lookup(ctx->process_hash_table,
180 (gconstpointer) (unsigned long) tid);
181
182 return tmp;
183 }
184
185 struct processtop* add_proc(struct lttngtop *ctx, int tid, char *comm,
186 unsigned long timestamp, char *hostname)
187 {
188 struct processtop *newproc;
189 struct host *host;
190
191 /* if the PID already exists, we just rename the process */
192 /* FIXME : need to integrate with clone/fork/exit to be accurate */
193 newproc = find_process_tid(ctx, tid, comm);
194
195 if (!newproc) {
196 newproc = g_new0(struct processtop, 1);
197 newproc->tid = tid;
198 newproc->birth = timestamp;
199 newproc->process_files_table = g_ptr_array_new();
200 newproc->files_history = NULL;
201 newproc->totalfileread = 0;
202 newproc->totalfilewrite = 0;
203 newproc->fileread = 0;
204 newproc->filewrite = 0;
205 newproc->syscall_info = NULL;
206 newproc->threadparent = NULL;
207 newproc->threads = g_ptr_array_new();
208 newproc->perf = g_hash_table_new(g_str_hash, g_str_equal);
209 g_ptr_array_add(ctx->process_table, newproc);
210 g_hash_table_insert(ctx->process_hash_table,
211 (gpointer) (unsigned long) tid, newproc);
212 if (lookup_tid_list(tid)) {
213 add_filter_tid_list(newproc);
214 }
215 ctx->nbnewthreads++;
216 ctx->nbthreads++;
217 }
218 newproc->comm = strdup(comm);
219 if (hostname) {
220 host = lookup_hostname_list(hostname);
221 if (!host)
222 host = add_hostname_list(hostname, 0);
223 if (!newproc->host || (newproc->host != host))
224 newproc->host = host;
225 if (is_hostname_filtered(hostname)) {
226 add_filter_tid_list(newproc);
227 }
228 }
229
230 return newproc;
231 }
232
233 struct processtop* update_proc(struct processtop* proc, int pid, int tid,
234 int ppid, int vpid, int vtid, int vppid, char *comm, char *hostname)
235 {
236 struct host *host;
237
238 if (proc) {
239 proc->pid = pid;
240 proc->tid = tid;
241 proc->ppid = ppid;
242 proc->vpid = vpid;
243 proc->vtid = vtid;
244 proc->vppid = vppid;
245 if (strcmp(proc->comm, comm) != 0) {
246 free(proc->comm);
247 proc->comm = strdup(comm);
248 }
249 if (hostname && !proc->host) {
250 host = lookup_hostname_list(hostname);
251 if (!host)
252 host = add_hostname_list(hostname, 0);
253 if (!proc->host || (proc->host != host))
254 proc->host = host;
255 if (is_hostname_filtered(hostname)) {
256 add_filter_tid_list(proc);
257 }
258 }
259 }
260 return proc;
261 }
262
263 /*
264 * This function just sets the time of death of a process.
265 * When we rotate the cputime we remove it from the process list.
266 */
267 void death_proc(struct lttngtop *ctx, int tid, char *comm,
268 unsigned long timestamp)
269 {
270 struct processtop *tmp;
271 tmp = find_process_tid(ctx, tid, comm);
272
273 g_hash_table_remove(ctx->process_hash_table,
274 (gpointer) (unsigned long) tid);
275 if (tmp && strcmp(tmp->comm, comm) == 0) {
276 tmp->death = timestamp;
277 ctx->nbdeadthreads++;
278 ctx->nbthreads--;
279 }
280 }
281
282 struct processtop* get_proc(struct lttngtop *ctx, int tid, char *comm,
283 unsigned long timestamp, char *hostname)
284 {
285 struct processtop *tmp;
286
287 tmp = find_process_tid(ctx, tid, comm);
288 if (tmp && strcmp(tmp->comm, comm) == 0) {
289 return tmp;
290 }
291 return add_proc(ctx, tid, comm, timestamp, hostname);
292 }
293
294 struct processtop *get_proc_pid(struct lttngtop *ctx, int tid, int pid,
295 unsigned long timestamp, char *hostname)
296 {
297 struct processtop *tmp;
298 tmp = find_process_tid(ctx, tid, NULL);
299 if (tmp && tmp->pid == pid)
300 return tmp;
301 return add_proc(ctx, tid, "Unknown", timestamp, hostname);
302 }
303
304 void add_thread(struct processtop *parent, struct processtop *thread)
305 {
306 gint i;
307 struct processtop *tmp;
308
309 if (!parent)
310 return;
311
312 for (i = 0; i < parent->threads->len; i++) {
313 tmp = g_ptr_array_index(parent->threads, i);
314 if (tmp == thread)
315 return;
316 }
317 g_ptr_array_add(parent->threads, thread);
318 }
319
320 struct cputime* add_cpu(int cpu)
321 {
322 struct cputime *newcpu;
323
324 newcpu = g_new0(struct cputime, 1);
325 newcpu->id = cpu;
326 newcpu->current_task = NULL;
327 newcpu->perf = g_hash_table_new(g_str_hash, g_str_equal);
328
329 g_ptr_array_add(lttngtop.cpu_table, newcpu);
330
331 return newcpu;
332 }
333 struct cputime* get_cpu(int cpu)
334 {
335 gint i;
336 struct cputime *tmp;
337
338 for (i = 0; i < lttngtop.cpu_table->len; i++) {
339 tmp = g_ptr_array_index(lttngtop.cpu_table, i);
340 if (tmp->id == cpu)
341 return tmp;
342 }
343
344 return add_cpu(cpu);
345 }
346
347 /*
348 * At the end of a sampling period, we need to display the cpu time for each
349 * process and to reset it to zero for the next period
350 */
351 void rotate_cputime(unsigned long end)
352 {
353 gint i;
354 struct cputime *tmp;
355 unsigned long elapsed;
356
357 for (i = 0; i < lttngtop.cpu_table->len; i++) {
358 tmp = g_ptr_array_index(lttngtop.cpu_table, i);
359 elapsed = end - tmp->task_start;
360 if (tmp->current_task) {
361 tmp->current_task->totalcpunsec += elapsed;
362 tmp->current_task->threadstotalcpunsec += elapsed;
363 if (tmp->current_task->pid != tmp->current_task->tid &&
364 tmp->current_task->threadparent) {
365 tmp->current_task->threadparent->threadstotalcpunsec += elapsed;
366 }
367 }
368 tmp->task_start = end;
369 }
370 }
371
372 void reset_perf_counter(gpointer key, gpointer value, gpointer user_data)
373 {
374 ((struct perfcounter*) value)->count = 0;
375 }
376
377 void copy_perf_counter(gpointer key, gpointer value, gpointer new_table)
378 {
379 struct perfcounter *newperf;
380
381 newperf = g_new0(struct perfcounter, 1);
382 newperf->count = ((struct perfcounter *) value)->count;
383 newperf->visible = ((struct perfcounter *) value)->visible;
384 newperf->sort = ((struct perfcounter *) value)->sort;
385 g_hash_table_insert((GHashTable *) new_table, strdup(key), newperf);
386 }
387
388 void copy_process_table(gpointer key, gpointer value, gpointer new_table)
389 {
390 g_hash_table_insert((GHashTable *) new_table, key, value);
391 }
392
393 void rotate_perfcounter() {
394 int i;
395 struct processtop *tmp;
396
397 for (i = 0; i < lttngtop.process_table->len; i++) {
398 tmp = g_ptr_array_index(lttngtop.process_table, i);
399 g_hash_table_foreach(tmp->perf, reset_perf_counter, NULL);
400 }
401 }
402
403 void cleanup_processtop()
404 {
405 gint i, j;
406 struct processtop *tmp;
407 struct files *tmpf; /* a temporary file */
408
409 for (i = 0; i < lttngtop.process_table->len; i++) {
410 tmp = g_ptr_array_index(lttngtop.process_table, i);
411 tmp->totalcpunsec = 0;
412 tmp->threadstotalcpunsec = 0;
413 tmp->fileread = 0;
414 tmp->filewrite = 0;
415
416 for (j = 0; j < tmp->process_files_table->len; j++) {
417 tmpf = g_ptr_array_index(tmp->process_files_table, j);
418 if (tmpf != NULL) {
419 tmpf->read = 0;
420 tmpf->write = 0;
421
422 if (tmpf->flag == __NR_close)
423 g_ptr_array_index(
424 tmp->process_files_table, j
425 ) = NULL;
426 }
427 }
428 }
429 }
430
431 void reset_global_counters()
432 {
433 lttngtop.nbnewproc = 0;
434 lttngtop.nbdeadproc = 0;
435 lttngtop.nbnewthreads = 0;
436 lttngtop.nbdeadthreads = 0;
437 lttngtop.nbnewfiles = 0;
438 lttngtop.nbclosedfiles = 0;
439 }
440
441 void copy_global_counters(struct lttngtop *dst)
442 {
443 dst->nbproc = lttngtop.nbproc;
444 dst->nbnewproc = lttngtop.nbnewproc;
445 dst->nbdeadproc = lttngtop.nbdeadproc;
446 dst->nbthreads = lttngtop.nbthreads;
447 dst->nbnewthreads = lttngtop.nbnewthreads;
448 dst->nbdeadthreads = lttngtop.nbdeadthreads;
449 dst->nbfiles = lttngtop.nbfiles;
450 dst->nbnewfiles = lttngtop.nbnewfiles;
451 dst->nbclosedfiles = lttngtop.nbclosedfiles;
452 reset_global_counters();
453 }
454
455 struct lttngtop* get_copy_lttngtop(unsigned long start, unsigned long end)
456 {
457 gint i, j;
458 unsigned long time;
459 struct lttngtop *dst;
460 struct processtop *tmp, *tmp2, *new;
461 struct cputime *tmpcpu, *newcpu;
462 struct files *tmpfile, *newfile;
463 struct kprobes *tmpprobe, *newprobe;
464
465 dst = g_new0(struct lttngtop, 1);
466 dst->start = start;
467 dst->end = end;
468 copy_global_counters(dst);
469 dst->process_table = g_ptr_array_new();
470 dst->files_table = g_ptr_array_new();
471 dst->cpu_table = g_ptr_array_new();
472 dst->kprobes_table = g_ptr_array_new();
473 dst->process_hash_table = g_hash_table_new(g_direct_hash, g_direct_equal);
474 g_hash_table_foreach(lttngtop.process_hash_table, copy_process_table,
475 dst->process_hash_table);
476
477 rotate_cputime(end);
478
479 for (i = 0; i < lttngtop.process_table->len; i++) {
480 tmp = g_ptr_array_index(lttngtop.process_table, i);
481 new = g_new0(struct processtop, 1);
482
483 memcpy(new, tmp, sizeof(struct processtop));
484 new->threads = g_ptr_array_new();
485 new->comm = strdup(tmp->comm);
486 new->process_files_table = g_ptr_array_new();
487 new->files_history = tmp->files_history;
488 new->perf = g_hash_table_new(g_str_hash, g_str_equal);
489 g_hash_table_foreach(tmp->perf, copy_perf_counter, new->perf);
490
491 /* compute the stream speed */
492 if (end - start != 0) {
493 time = (end - start) / NSEC_PER_SEC;
494 new->fileread = new->fileread/(time);
495 new->filewrite = new->filewrite/(time);
496 }
497
498 for (j = 0; j < tmp->process_files_table->len; j++) {
499 tmpfile = g_ptr_array_index(tmp->process_files_table, j);
500
501 newfile = malloc(sizeof(struct files));
502
503 if (tmpfile != NULL) {
504 memcpy(newfile, tmpfile, sizeof(struct files));
505 newfile->name = strdup(tmpfile->name);
506 newfile->ref = new;
507 g_ptr_array_add(new->process_files_table,
508 newfile);
509 g_ptr_array_add(dst->files_table, newfile);
510 } else {
511 g_ptr_array_add(new->process_files_table, NULL);
512 g_ptr_array_add(dst->files_table, NULL);
513 }
514 /*
515 * if the process died during the last period, we remove all
516 * files associated with if after the copy
517 */
518 if (tmp->death > 0 && tmp->death < end) {
519 /* FIXME : close the files before */
520 g_ptr_array_remove(tmp->process_files_table, tmpfile);
521 g_free(tmpfile);
522 }
523 }
524 g_ptr_array_add(dst->process_table, new);
525
526 /*
527 * if the process died during the last period, we remove it from
528 * the current process list after the copy
529 */
530 if (tmp->death > 0 && tmp->death < end) {
531 g_ptr_array_remove(lttngtop.process_table, tmp);
532 /* FIXME : TRUE does not mean clears the object in it */
533 g_ptr_array_free(tmp->threads, TRUE);
534 free(tmp->comm);
535 g_ptr_array_free(tmp->process_files_table, TRUE);
536 /* FIXME : clear elements */
537 g_hash_table_destroy(tmp->perf);
538 g_free(tmp);
539 }
540 }
541 rotate_perfcounter();
542
543 for (i = 0; i < lttngtop.cpu_table->len; i++) {
544 tmpcpu = g_ptr_array_index(lttngtop.cpu_table, i);
545 newcpu = g_new0(struct cputime, 1);
546 memcpy(newcpu, tmpcpu, sizeof(struct cputime));
547 newcpu->perf = g_hash_table_new(g_str_hash, g_str_equal);
548 g_hash_table_foreach(tmpcpu->perf, copy_perf_counter, newcpu->perf);
549 /*
550 * note : we don't care about the current process pointer in the copy
551 * so the reference is invalid after the memcpy
552 */
553 g_ptr_array_add(dst->cpu_table, newcpu);
554 }
555 if (lttngtop.kprobes_table) {
556 for (i = 0; i < lttngtop.kprobes_table->len; i++) {
557 tmpprobe = g_ptr_array_index(lttngtop.kprobes_table, i);
558 newprobe = g_new0(struct kprobes, 1);
559 memcpy(newprobe, tmpprobe, sizeof(struct kprobes));
560 tmpprobe->count = 0;
561 g_ptr_array_add(dst->kprobes_table, newprobe);
562 }
563 }
564 /* FIXME : better algo */
565 /* create the threads index if required */
566 for (i = 0; i < dst->process_table->len; i++) {
567 tmp = g_ptr_array_index(dst->process_table, i);
568 if (tmp->pid == tmp->tid) {
569 for (j = 0; j < dst->process_table->len; j++) {
570 tmp2 = g_ptr_array_index(dst->process_table, j);
571 if (tmp2->pid == tmp->pid) {
572 tmp2->threadparent = tmp;
573 g_ptr_array_add(tmp->threads, tmp2);
574 }
575 }
576 }
577 }
578
579 // update_global_stats(dst);
580 cleanup_processtop();
581
582 return dst;
583 }
584
585
586 enum bt_cb_ret handle_statedump_process_state(struct bt_ctf_event *call_data,
587 void *private_data)
588 {
589 const struct bt_definition *scope;
590 struct processtop *proc;
591 unsigned long timestamp;
592 int64_t pid, tid, ppid, vtid, vpid, vppid;
593 char *procname, *hostname = NULL;
594
595 timestamp = bt_ctf_get_timestamp(call_data);
596 if (timestamp == -1ULL)
597 goto error;
598
599 scope = bt_ctf_get_top_level_scope(call_data,
600 BT_EVENT_FIELDS);
601 pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
602 scope, "_pid"));
603 if (bt_ctf_field_get_error()) {
604 fprintf(stderr, "Missing pid context info\n");
605 goto error;
606 }
607 ppid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
608 scope, "_ppid"));
609 if (bt_ctf_field_get_error()) {
610 goto end;
611 }
612 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
613 scope, "_tid"));
614 if (bt_ctf_field_get_error()) {
615 fprintf(stderr, "Missing tid context info\n");
616 goto error;
617 }
618 vtid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
619 scope, "_vtid"));
620 if (bt_ctf_field_get_error()) {
621 fprintf(stderr, "Missing vtid context info\n");
622 goto error;
623 }
624 vpid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
625 scope, "_vpid"));
626 if (bt_ctf_field_get_error()) {
627 fprintf(stderr, "Missing vpid context info\n");
628 goto error;
629 }
630 vppid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
631 scope, "_vppid"));
632 if (bt_ctf_field_get_error()) {
633 fprintf(stderr, "Missing vppid context info\n");
634 goto error;
635 }
636
637 scope = bt_ctf_get_top_level_scope(call_data,
638 BT_EVENT_FIELDS);
639 procname = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
640 scope, "_name"));
641 if (bt_ctf_field_get_error()) {
642 fprintf(stderr, "Missing process name context info\n");
643 goto error;
644 }
645
646 proc = find_process_tid(&lttngtop, tid, procname);
647 if (proc == NULL)
648 proc = add_proc(&lttngtop, tid, procname, timestamp, hostname);
649 update_proc(proc, pid, tid, ppid, vpid, vtid, vppid, procname, hostname);
650
651 if (proc) {
652 free(proc->comm);
653 proc->comm = strdup(procname);
654 proc->pid = pid;
655 }
656
657 end:
658 return BT_CB_OK;
659
660 error:
661 return BT_CB_ERROR_STOP;
662 }
663
664 struct tm format_timestamp(uint64_t timestamp)
665 {
666 struct tm tm;
667 uint64_t ts_sec = 0, ts_nsec;
668 time_t time_s;
669
670 ts_nsec = timestamp;
671 ts_sec += ts_nsec / NSEC_PER_SEC;
672 ts_nsec = ts_nsec % NSEC_PER_SEC;
673
674 time_s = (time_t) ts_sec;
675
676 localtime_r(&time_s, &tm);
677
678 return tm;
679 }
680
681 int *lookup_tid_list(int tid)
682 {
683 if (!tid_filter_list)
684 return NULL;
685
686 return g_hash_table_lookup(tid_filter_list, (gpointer) &tid);
687 }
688
689 struct host *lookup_hostname_list(const char *hostname)
690 {
691 if (!hostname || !global_host_list)
692 return NULL;
693
694 return g_hash_table_lookup(global_host_list, (gpointer) hostname);
695 }
696
697 int is_hostname_filtered(const char *hostname)
698 {
699 struct host *host;
700
701 host = lookup_hostname_list(hostname);
702 if (host)
703 return host->filter;
704 return 0;
705 }
706
707 int *lookup_filter_tid_list(int tid)
708 {
709 return g_hash_table_lookup(global_filter_list, (gpointer) &tid);
710 }
711
712 void add_filter_tid_list(struct processtop *proc)
713 {
714 unsigned long *hash_tid;
715
716 hash_tid = malloc(sizeof(unsigned long));
717 *hash_tid = proc->tid;
718 g_hash_table_insert(global_filter_list,
719 (gpointer) (unsigned long) hash_tid, proc);
720 }
721
722 void remove_filter_tid_list(int tid)
723 {
724 g_hash_table_remove(global_filter_list,
725 (gpointer) (unsigned long) &tid);
726 }
727
728 struct host *add_hostname_list(char *hostname, int filter)
729 {
730 struct host *host;
731
732 host = lookup_hostname_list(hostname);
733 if (host)
734 return host;
735
736 host = g_new0(struct host, 1);
737 host->hostname = strdup(hostname);
738 host->filter = filter;
739 g_hash_table_insert(global_host_list,
740 (gpointer) host->hostname,
741 (gpointer) host);
742
743 return host;
744 }
745
746 void update_hostname_filter(struct host *host)
747 {
748 struct processtop *tmp;
749 int i;
750
751 for (i = 0; i < lttngtop.process_table->len; i++) {
752 tmp = g_ptr_array_index(lttngtop.process_table, i);
753 if (tmp->host == host) {
754 if (host->filter)
755 add_filter_tid_list(tmp);
756 else
757 remove_filter_tid_list(tmp->tid);
758 }
759 }
760 }
This page took 0.068549 seconds and 4 git commands to generate.