prepare the 0.3 release
[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, NULL, 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 if (tmpfile->name)
506 newfile->name = strdup(tmpfile->name);
507 else
508 newfile->name = NULL;
509 newfile->ref = new;
510 g_ptr_array_add(new->process_files_table,
511 newfile);
512 g_ptr_array_add(dst->files_table, newfile);
513 } else {
514 g_ptr_array_add(new->process_files_table, NULL);
515 g_ptr_array_add(dst->files_table, NULL);
516 }
517 /*
518 * if the process died during the last period, we remove all
519 * files associated with if after the copy
520 */
521 if (tmp->death > 0 && tmp->death < end) {
522 /* FIXME : close the files before */
523 g_ptr_array_remove(tmp->process_files_table, tmpfile);
524 g_free(tmpfile);
525 }
526 }
527 g_ptr_array_add(dst->process_table, new);
528
529 /*
530 * if the process died during the last period, we remove it from
531 * the current process list after the copy
532 */
533 if (tmp->death > 0 && tmp->death < end) {
534 g_ptr_array_remove(lttngtop.process_table, tmp);
535 /* FIXME : TRUE does not mean clears the object in it */
536 g_ptr_array_free(tmp->threads, TRUE);
537 free(tmp->comm);
538 g_ptr_array_free(tmp->process_files_table, TRUE);
539 /* FIXME : clear elements */
540 g_hash_table_destroy(tmp->perf);
541 g_free(tmp);
542 }
543 }
544 rotate_perfcounter();
545
546 for (i = 0; i < lttngtop.cpu_table->len; i++) {
547 tmpcpu = g_ptr_array_index(lttngtop.cpu_table, i);
548 newcpu = g_new0(struct cputime, 1);
549 memcpy(newcpu, tmpcpu, sizeof(struct cputime));
550 newcpu->perf = g_hash_table_new(g_str_hash, g_str_equal);
551 g_hash_table_foreach(tmpcpu->perf, copy_perf_counter, newcpu->perf);
552 /*
553 * note : we don't care about the current process pointer in the copy
554 * so the reference is invalid after the memcpy
555 */
556 g_ptr_array_add(dst->cpu_table, newcpu);
557 }
558 if (lttngtop.kprobes_table) {
559 for (i = 0; i < lttngtop.kprobes_table->len; i++) {
560 tmpprobe = g_ptr_array_index(lttngtop.kprobes_table, i);
561 newprobe = g_new0(struct kprobes, 1);
562 memcpy(newprobe, tmpprobe, sizeof(struct kprobes));
563 tmpprobe->count = 0;
564 g_ptr_array_add(dst->kprobes_table, newprobe);
565 }
566 }
567 /* FIXME : better algo */
568 /* create the threads index if required */
569 for (i = 0; i < dst->process_table->len; i++) {
570 tmp = g_ptr_array_index(dst->process_table, i);
571 if (tmp->pid == tmp->tid) {
572 for (j = 0; j < dst->process_table->len; j++) {
573 tmp2 = g_ptr_array_index(dst->process_table, j);
574 if (tmp2->pid == tmp->pid) {
575 tmp2->threadparent = tmp;
576 g_ptr_array_add(tmp->threads, tmp2);
577 }
578 }
579 }
580 }
581
582 // update_global_stats(dst);
583 cleanup_processtop();
584
585 return dst;
586 }
587
588
589 enum bt_cb_ret handle_statedump_process_state(struct bt_ctf_event *call_data,
590 void *private_data)
591 {
592 const struct bt_definition *scope;
593 struct processtop *proc;
594 unsigned long timestamp;
595 int64_t pid, tid, ppid, vtid, vpid, vppid;
596 char *procname = NULL, *hostname = NULL;
597
598 timestamp = bt_ctf_get_timestamp(call_data);
599 if (timestamp == -1ULL)
600 goto error;
601
602 scope = bt_ctf_get_top_level_scope(call_data,
603 BT_EVENT_FIELDS);
604 pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
605 scope, "_pid"));
606 if (bt_ctf_field_get_error()) {
607 fprintf(stderr, "Missing pid context info\n");
608 goto error;
609 }
610 ppid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
611 scope, "_ppid"));
612 if (bt_ctf_field_get_error()) {
613 goto end;
614 }
615 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
616 scope, "_tid"));
617 if (bt_ctf_field_get_error()) {
618 fprintf(stderr, "Missing tid context info\n");
619 goto error;
620 }
621 vtid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
622 scope, "_vtid"));
623 if (bt_ctf_field_get_error()) {
624 fprintf(stderr, "Missing vtid context info\n");
625 goto error;
626 }
627 vpid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
628 scope, "_vpid"));
629 if (bt_ctf_field_get_error()) {
630 fprintf(stderr, "Missing vpid context info\n");
631 goto error;
632 }
633 vppid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
634 scope, "_vppid"));
635 if (bt_ctf_field_get_error()) {
636 fprintf(stderr, "Missing vppid context info\n");
637 goto error;
638 }
639
640 scope = bt_ctf_get_top_level_scope(call_data,
641 BT_EVENT_FIELDS);
642 procname = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
643 scope, "_name"));
644 if (bt_ctf_field_get_error()) {
645 fprintf(stderr, "Missing process name context info\n");
646 goto error;
647 }
648
649 proc = find_process_tid(&lttngtop, tid, procname);
650 if (proc == NULL)
651 proc = add_proc(&lttngtop, tid, procname, timestamp, hostname);
652 update_proc(proc, pid, tid, ppid, vpid, vtid, vppid, procname, hostname);
653
654 if (proc) {
655 free(proc->comm);
656 proc->comm = strdup(procname);
657 proc->pid = pid;
658 }
659
660 end:
661 return BT_CB_OK;
662
663 error:
664 return BT_CB_ERROR_STOP;
665 }
666
667 struct tm format_timestamp(uint64_t timestamp)
668 {
669 struct tm tm;
670 uint64_t ts_sec = 0, ts_nsec;
671 time_t time_s;
672
673 ts_nsec = timestamp;
674 ts_sec += ts_nsec / NSEC_PER_SEC;
675 ts_nsec = ts_nsec % NSEC_PER_SEC;
676
677 time_s = (time_t) ts_sec;
678
679 localtime_r(&time_s, &tm);
680
681 return tm;
682 }
683
684 int *lookup_tid_list(int tid)
685 {
686 if (!tid_filter_list)
687 return NULL;
688
689 return g_hash_table_lookup(tid_filter_list, (gpointer) &tid);
690 }
691
692 struct host *lookup_hostname_list(const char *hostname)
693 {
694 if (!hostname || !global_host_list)
695 return NULL;
696
697 return g_hash_table_lookup(global_host_list, (gpointer) hostname);
698 }
699
700 int is_hostname_filtered(const char *hostname)
701 {
702 struct host *host;
703
704 host = lookup_hostname_list(hostname);
705 if (host)
706 return host->filter;
707 return 0;
708 }
709
710 int *lookup_filter_tid_list(int tid)
711 {
712 return g_hash_table_lookup(global_filter_list, (gpointer) &tid);
713 }
714
715 void add_filter_tid_list(struct processtop *proc)
716 {
717 unsigned long *hash_tid;
718
719 hash_tid = malloc(sizeof(unsigned long));
720 *hash_tid = proc->tid;
721 g_hash_table_insert(global_filter_list,
722 (gpointer) (unsigned long) hash_tid, proc);
723 }
724
725 void remove_filter_tid_list(int tid)
726 {
727 g_hash_table_remove(global_filter_list,
728 (gpointer) (unsigned long) &tid);
729 }
730
731 struct host *add_hostname_list(char *hostname, int filter)
732 {
733 struct host *host;
734
735 host = lookup_hostname_list(hostname);
736 if (host)
737 return host;
738
739 host = g_new0(struct host, 1);
740 host->hostname = strdup(hostname);
741 host->filter = filter;
742 g_hash_table_insert(global_host_list,
743 (gpointer) host->hostname,
744 (gpointer) host);
745
746 return host;
747 }
748
749 void update_hostname_filter(struct host *host)
750 {
751 struct processtop *tmp;
752 int i;
753
754 for (i = 0; i < lttngtop.process_table->len; i++) {
755 tmp = g_ptr_array_index(lttngtop.process_table, i);
756 if (tmp->host == host) {
757 if (host->filter)
758 add_filter_tid_list(tmp);
759 else
760 remove_filter_tid_list(tmp->tid);
761 }
762 }
763 }
764
765 char *lookup_procname(const char *procname)
766 {
767 if (!procname || !global_procname_list)
768 return NULL;
769
770 return g_hash_table_lookup(global_procname_list, (gpointer) procname);
771 }
772
773 char *add_procname_list(char *procname, int filter)
774 {
775 char *proc;
776
777 proc = lookup_procname(procname);
778 if (proc)
779 return proc;
780
781 proc = strdup(procname);
782 g_hash_table_insert(global_procname_list,
783 (gpointer) procname, (gpointer) procname);
784
785 return proc;
786 }
This page took 0.070397 seconds and 4 git commands to generate.