filtering in GUI working
[lttngtop.git] / src / cursesdisplay.c
CommitLineData
1fc22eb4 1/*
aa15ac1c 2 * Copyright (C) 2011-2012 Julien Desfossez
1fc22eb4
JD
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 *
71bd7ce1
AM
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.
1fc22eb4
JD
16 */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <signal.h>
21#include <string.h>
22#include <ncurses.h>
23#include <panel.h>
24#include <pthread.h>
25#include <semaphore.h>
26
27#include "cursesdisplay.h"
28#include "lttngtoptypes.h"
b093de8a 29#include "iostreamtop.h"
1fc22eb4
JD
30#include "common.h"
31
32#define DEFAULT_DELAY 15
33#define MAX_LINE_LENGTH 50
34#define MAX_LOG_LINES 4
35
36/* to prevent concurrent updates of the different windows */
37sem_t update_display_sem;
38
39char *termtype;
40WINDOW *footer, *header, *center, *status;
0d91c12a
JD
41WINDOW *pref_panel_window = NULL;
42PANEL *pref_panel, *main_panel;
1fc22eb4 43
0d91c12a 44int pref_panel_visible = 0;
3b15348c 45int pref_line_selected = 0;
41ff0645 46int pref_current_sort = 0;
1fc22eb4
JD
47
48int last_display_index, currently_displayed_index;
49
50struct processtop *selected_process = NULL;
1fc22eb4
JD
51int selected_ret;
52
53int selected_line = 0; /* select bar position */
54int selected_in_list = 0; /* selection relative to the whole list */
55int list_offset = 0; /* first index in the list to display (scroll) */
56int nb_log_lines = 0;
57char log_lines[MAX_LINE_LENGTH * MAX_LOG_LINES + MAX_LOG_LINES];
58
59int max_elements = 80;
60
e15ed00a 61int toggle_threads = 1;
1402044a 62int toggle_virt = -1;
1fc22eb4 63int toggle_pause = -1;
1fc22eb4
JD
64
65int max_center_lines;
66
67pthread_t keyboard_thread;
68
1402044a 69struct header_view cputopview[6];
89f1e0d1 70struct header_view iostreamtopview[3];
32647247 71struct header_view fileview[3];
246d5992 72struct header_view kprobeview[2];
3b15348c 73
1fc22eb4
JD
74void reset_ncurses()
75{
76 curs_set(1);
77 endwin();
ae9e85c7 78 quit = 1;
33572a17
JD
79 sem_post(&pause_sem);
80 sem_post(&timer);
81 sem_post(&goodtodisplay);
1402044a
JD
82 sem_post(&end_trace_sem);
83 sem_post(&goodtoupdate);
1fc22eb4
JD
84}
85
86static void handle_sigterm(int signal)
87{
ae9e85c7 88 pthread_cancel(keyboard_thread);
1fc22eb4
JD
89 reset_ncurses();
90}
91
92void init_screen()
93{
94 initscr();
95 noecho();
96 halfdelay(DEFAULT_DELAY);
97 nonl();
98 intrflush(stdscr, false);
99 keypad(stdscr, true);
100 curs_set(0);
101
102 if (has_colors()) {
103 start_color();
104 init_pair(1, COLOR_RED, COLOR_BLACK); /* - */
105 init_pair(2, COLOR_GREEN, COLOR_BLACK); /* + */
106 init_pair(3, COLOR_BLACK, COLOR_WHITE); /* keys */
107 init_pair(4, COLOR_WHITE, COLOR_GREEN); /* keys activated */
da4353bb
JD
108 init_pair(5, COLOR_BLACK, COLOR_YELLOW); /* select line */
109 init_pair(6, COLOR_GREEN, COLOR_BLACK); /* selected process */
110 init_pair(7, COLOR_RED, COLOR_YELLOW); /* selected process + line*/
1fc22eb4
JD
111 }
112 termtype = getenv("TERM");
113 if (!strcmp(termtype, "xterm") || !strcmp(termtype, "xterm-color") ||
114 !strcmp(termtype, "vt220")) {
115 define_key("\033[H", KEY_HOME);
116 define_key("\033[F", KEY_END);
117 define_key("\033OP", KEY_F(1));
118 define_key("\033OQ", KEY_F(2));
119 define_key("\033OR", KEY_F(3));
120 define_key("\033OS", KEY_F(4));
121 define_key("\0330U", KEY_F(6));
122 define_key("\033[11~", KEY_F(1));
123 define_key("\033[12~", KEY_F(2));
124 define_key("\033[13~", KEY_F(3));
125 define_key("\033[14~", KEY_F(4));
126 define_key("\033[16~", KEY_F(6));
127 define_key("\033[17;2~", KEY_F(18));
128 }
129 signal(SIGTERM, handle_sigterm);
ae9e85c7 130 signal(SIGINT, handle_sigterm);
1fc22eb4
JD
131 mousemask(BUTTON1_CLICKED, NULL);
132 refresh();
133}
134
135WINDOW *create_window(int height, int width, int startx, int starty)
136{
137 WINDOW *win;
138 win = newwin(height, width, startx, starty);
139 box(win, 0 , 0);
140 wrefresh(win);
141 return win;
142}
143
144WINDOW *create_window_no_border(int height, int width, int startx, int starty)
145{
146 WINDOW *win;
147 win = newwin(height, width, startx, starty);
148 wrefresh(win);
149 return win;
150}
151
152void print_digit(WINDOW *win, int digit)
153{
154 if (digit < 0) {
155 wattron(win, COLOR_PAIR(1));
156 wprintw(win, "%d", digit);
157 wattroff(win, COLOR_PAIR(1));
158 } else if (digit > 0) {
159 wattron(win, COLOR_PAIR(2));
160 wprintw(win, "+%d", digit);
161 wattroff(win, COLOR_PAIR(2));
162 } else {
163 wprintw(win, "0");
164 }
165}
166
167void print_digits(WINDOW *win, int first, int second)
168{
169 wprintw(win, "(");
170 print_digit(win, first);
171 wprintw(win, ", ");
172 print_digit(win, second);
173 wprintw(win, ")");
174}
175
176void print_headers(int line, char *desc, int value, int first, int second)
177{
178 wattron(header, A_BOLD);
179 mvwprintw(header, line, 4, "%s", desc);
180 wattroff(header, A_BOLD);
e05a35a6 181 mvwprintw(header, line, 16, "%d", value);
1fc22eb4
JD
182 wmove(header, line, 24);
183 print_digits(header, first, second);
184 wmove(header, line, 40);
185}
186
187void set_window_title(WINDOW *win, char *title)
188{
189 wattron(win, A_BOLD);
190 mvwprintw(win, 0, 1, title);
191 wattroff(win, A_BOLD);
192}
193
194void print_log(char *str)
195{
196 int i;
197 int current_line = 1;
198 int current_char = 1;
199 char *tmp, *tmp2;
200 /* rotate the line buffer */
201 if (nb_log_lines >= MAX_LOG_LINES) {
202 tmp = strndup(log_lines, MAX_LINE_LENGTH * MAX_LOG_LINES + MAX_LOG_LINES);
203 tmp2 = strchr(tmp, '\n');
204 memset(log_lines, '\0', strlen(log_lines));
205 strncat(log_lines, tmp2 + 1, strlen(tmp2) - 1);
206 log_lines[strlen(log_lines)] = '\n';
207 log_lines[strlen(log_lines)] = '\0';
208 free(tmp);
209 }
210 nb_log_lines++;
211
212 strncat(log_lines, str, MAX_LINE_LENGTH - 1);
213
214 if (nb_log_lines < MAX_LOG_LINES)
215 log_lines[strlen(log_lines)] = '\n';
216 log_lines[strlen(log_lines)] = '\0';
217
218 werase(status);
219 box(status, 0 , 0);
220 set_window_title(status, "Status");
221 for (i = 0; i < strlen(log_lines); i++) {
222 if (log_lines[i] == '\n') {
223 wmove(status, ++current_line, 1);
224 current_char = 1;
225 } else {
b093de8a
MB
226 mvwprintw(status, current_line, current_char++, "%c",
227 log_lines[i]);
1fc22eb4
JD
228 }
229 }
230 wrefresh(status);
231}
232
635dc837
JD
233int process_selected(struct processtop *process)
234{
da4353bb
JD
235 if (lookup_filter_tid_list(process->tid))
236 return 1;
635dc837
JD
237 return 0;
238}
239
240void update_selected_processes()
241{
242 if (process_selected(selected_process)) {
da4353bb 243 remove_filter_tid_list(selected_process->tid);
635dc837 244 } else {
da4353bb 245 add_filter_tid_list(selected_process->tid, selected_process);
635dc837
JD
246 }
247}
248
1fc22eb4
JD
249void print_key(WINDOW *win, char *key, char *desc, int toggle)
250{
251 int pair;
252 if (toggle > 0)
253 pair = 4;
254 else
255 pair = 3;
256 wattron(win, COLOR_PAIR(pair));
257 wprintw(footer, "%s", key);
258 wattroff(win, COLOR_PAIR(pair));
259 wprintw(footer, ":%s", desc);
260}
261
262void update_footer()
263{
264 sem_wait(&update_display_sem);
265 werase(footer);
266 wmove(footer, 1, 1);
267 print_key(footer, "F2", "CPUtop ", current_view == cpu);
268 print_key(footer, "F3", "PerfTop ", current_view == perf);
e7be7d41 269 print_key(footer, "F4", "IOTop ", current_view == iostream);
1fc22eb4 270 print_key(footer, "Enter", "Details ", current_view == process_details);
635dc837 271 print_key(footer, "Space", "Highlight ", 0);
d33aae69 272 print_key(footer, "q", "Quit ", 0);
f9ff6939 273 print_key(footer, "r", "Pref ", 0);
e15ed00a 274 print_key(footer, "t", "Threads ", toggle_threads);
1402044a 275 print_key(footer, "v", "Virt ", toggle_virt);
1fc22eb4
JD
276 print_key(footer, "p", "Pause ", toggle_pause);
277
278 wrefresh(footer);
279 sem_post(&update_display_sem);
280}
281
282void basic_header()
283{
284 werase(header);
285 box(header, 0 , 0);
286 set_window_title(header, "Statistics for interval [gathering data...[");
287 wattron(header, A_BOLD);
288 mvwprintw(header, 1, 4, "CPUs");
e05a35a6 289 mvwprintw(header, 2, 4, "Threads");
dc8f04dd 290 mvwprintw(header, 3, 4, "FDs");
1fc22eb4
JD
291 wattroff(header, A_BOLD);
292 wrefresh(header);
293}
294
69362330
JD
295static void scale_unit(uint64_t bytes, char *ret)
296{
297 if (bytes >= 1000000000)
298 sprintf(ret, "%" PRIu64 "G", bytes/1000000000);
299 if (bytes >= 1000000)
300 sprintf(ret, "%" PRIu64 "M", bytes/1000000);
301 else if (bytes >= 1000)
302 sprintf(ret, "%" PRIu64 "K", bytes/1000);
303 else
304 sprintf(ret, "%" PRIu64, bytes);
305}
41ff0645 306
69362330
JD
307uint64_t total_io()
308{
309 int i;
310 struct processtop *tmp;
311 uint64_t total = 0;
312
313 for (i = 0; i < data->process_table->len; i++) {
314 tmp = g_ptr_array_index(data->process_table, i);
315 total += tmp->fileread;
316 total += tmp->filewrite;
317 }
318
319 return total;
320}
321
1fc22eb4
JD
322void update_header()
323{
91be6bb5
JD
324 struct tm start, end;
325 uint64_t ts_nsec_start, ts_nsec_end;
69362330 326 char io[4];
91be6bb5
JD
327
328 ts_nsec_start = data->start % NSEC_PER_SEC;
329 start = format_timestamp(data->start);
330
331 ts_nsec_end = data->end % NSEC_PER_SEC;
332 end = format_timestamp(data->end);
333
1fc22eb4
JD
334 werase(header);
335 box(header, 0 , 0);
336 set_window_title(header, "Statistics for interval ");
337 wattron(header, A_BOLD);
91be6bb5
JD
338
339 wprintw(header, "[%02d:%02d:%02d.%09" PRIu64 ", %02d:%02d:%02d.%09" PRIu64 "[",
340 start.tm_hour, start.tm_min, start.tm_sec, ts_nsec_start,
341 end.tm_hour, end.tm_min, end.tm_sec, ts_nsec_end);
1fc22eb4
JD
342 mvwprintw(header, 1, 4, "CPUs");
343 wattroff(header, A_BOLD);
344 wprintw(header, "\t%d\t(max/cpu : %0.2f%)", data->cpu_table->len,
345 100.0/data->cpu_table->len);
e05a35a6 346 print_headers(2, "Threads", data->nbthreads, data->nbnewthreads,
1fc22eb4 347 -1*(data->nbdeadthreads));
dc8f04dd 348 print_headers(3, "FDs", data->nbfiles, data->nbnewfiles,
1fc22eb4 349 -1*(data->nbclosedfiles));
69362330
JD
350 scale_unit(total_io(), io);
351 mvwprintw(header, 3, 43, "%sB/sec", io);
1fc22eb4
JD
352 wrefresh(header);
353}
354
355gint sort_by_cpu_desc(gconstpointer p1, gconstpointer p2)
356{
357 struct processtop *n1 = *(struct processtop **)p1;
358 struct processtop *n2 = *(struct processtop **)p2;
359 unsigned long totaln1 = n1->totalcpunsec;
360 unsigned long totaln2 = n2->totalcpunsec;
361
362 if (totaln1 < totaln2)
363 return 1;
364 if (totaln1 == totaln2)
365 return 0;
366 return -1;
367}
368
3b15348c
JD
369gint sort_by_tid_desc(gconstpointer p1, gconstpointer p2)
370{
371 struct processtop *n1 = *(struct processtop **)p1;
372 struct processtop *n2 = *(struct processtop **)p2;
373 unsigned long totaln1 = n1->tid;
374 unsigned long totaln2 = n2->tid;
375
376 if (totaln1 < totaln2)
377 return 1;
378 if (totaln1 == totaln2)
379 return 0;
380 return -1;
381}
382
383gint sort_by_pid_desc(gconstpointer p1, gconstpointer p2)
384{
385 struct processtop *n1 = *(struct processtop **)p1;
386 struct processtop *n2 = *(struct processtop **)p2;
387 unsigned long totaln1 = n1->pid;
388 unsigned long totaln2 = n2->pid;
389
390 if (totaln1 < totaln2)
391 return 1;
392 if (totaln1 == totaln2)
393 return 0;
394 return -1;
395}
396
89f1e0d1
JD
397gint sort_by_process_read_desc(gconstpointer p1, gconstpointer p2)
398{
399 struct processtop *n1 = *(struct processtop **)p1;
400 struct processtop *n2 = *(struct processtop **)p2;
401 unsigned long totaln1 = n1->fileread;
402 unsigned long totaln2 = n2->fileread;
403
404 if (totaln1 < totaln2)
405 return 1;
406 if (totaln1 == totaln2)
407 return 0;
408 return -1;
409}
410
411gint sort_by_process_write_desc(gconstpointer p1, gconstpointer p2)
412{
413 struct processtop *n1 = *(struct processtop **)p1;
414 struct processtop *n2 = *(struct processtop **)p2;
415 unsigned long totaln1 = n1->filewrite;
416 unsigned long totaln2 = n2->filewrite;
417
418 if (totaln1 < totaln2)
419 return 1;
420 if (totaln1 == totaln2)
421 return 0;
422 return -1;
423}
424
425gint sort_by_process_total_desc(gconstpointer p1, gconstpointer p2)
426{
427 struct processtop *n1 = *(struct processtop **)p1;
428 struct processtop *n2 = *(struct processtop **)p2;
41f5890b
JD
429 unsigned long totaln1 = n1->totalfilewrite + n1->totalfileread;
430 unsigned long totaln2 = n2->totalfilewrite + n2->totalfileread;
89f1e0d1
JD
431
432 if (totaln1 < totaln2)
433 return 1;
434 if (totaln1 == totaln2)
435 return 0;
436 return -1;
437}
438
32647247
JD
439gint sort_by_file_read_desc(gconstpointer p1, gconstpointer p2)
440{
441 struct files *n1 = *(struct files **)p1;
442 struct files *n2 = *(struct files **)p2;
443 unsigned long totaln1;
444 unsigned long totaln2;
445
446 totaln1 = n1->read;
447 totaln2 = n2->read;
448
449 if (totaln1 < totaln2)
450 return 1;
451 if (totaln1 == totaln2)
452 return 0;
453 return -1;
454}
455
456gint sort_by_file_write_desc(gconstpointer p1, gconstpointer p2)
457{
458 struct files *n1 = *(struct files **)p1;
459 struct files *n2 = *(struct files **)p2;
460 unsigned long totaln1;
461 unsigned long totaln2;
462
463 totaln1 = n1->write;
464 totaln2 = n2->write;
465
466 if (totaln1 < totaln2)
467 return 1;
468 if (totaln1 == totaln2)
469 return 0;
470 return -1;
471}
472
473gint sort_by_file_fd_desc(gconstpointer p1, gconstpointer p2)
474{
475 struct files *n1 = *(struct files **)p1;
476 struct files *n2 = *(struct files **)p2;
477 unsigned long totaln1;
478 unsigned long totaln2;
479
480 totaln1 = n1->fd;
481 totaln2 = n2->fd;
482
483 if (totaln1 < totaln2)
484 return 1;
485 if (totaln1 == totaln2)
486 return 0;
487 return -1;
488}
489
1fc22eb4
JD
490gint sort_by_cpu_group_by_threads_desc(gconstpointer p1, gconstpointer p2)
491{
492 struct processtop *n1 = *(struct processtop **)p1;
493 struct processtop *n2 = *(struct processtop **)p2;
494 unsigned long totaln1 = n1->threadstotalcpunsec;
495 unsigned long totaln2 = n2->threadstotalcpunsec;
496
497 if (totaln1 < totaln2)
498 return 1;
499 if (totaln1 == totaln2)
500 return 0;
501 return -1;
502}
503
fbbda4da
JD
504void update_kprobes_display()
505{
506 int i, column;
246d5992
JD
507 struct kprobes *probe;
508 int header_offset = 2;
509 int current_line = 0;
fbbda4da 510
246d5992 511 set_window_title(center, "Kprobes Top ");
fbbda4da
JD
512 wattron(center, A_BOLD);
513 column = 1;
246d5992
JD
514 for (i = 0; i < 2; i++) {
515 if (kprobeview[i].sort) {
fbbda4da
JD
516 wattron(center, A_UNDERLINE);
517 pref_current_sort = i;
518 }
246d5992 519 mvwprintw(center, 1, column, "%s", kprobeview[i].title);
fbbda4da 520 wattroff(center, A_UNDERLINE);
246d5992 521 column += 30;
fbbda4da
JD
522 }
523 wattroff(center, A_BOLD);
246d5992
JD
524
525 for (i = 0; i < data->kprobes_table->len; i++) {
526 column = 1;
527 probe = g_ptr_array_index(data->kprobes_table, i);
528 mvwprintw(center, current_line + header_offset, column,
529 "%s", probe->probe_name + 6);
530 column += 30;
531 mvwprintw(center, current_line + header_offset, column,
532 "%d", probe->count);
533 current_line++;
534 }
fbbda4da
JD
535}
536
1fc22eb4
JD
537void update_cputop_display()
538{
539 int i;
540 int header_offset = 2;
541 struct processtop *tmp;
542 unsigned long elapsed;
543 double maxcputime;
544 int nblinedisplayed = 0;
545 int current_line = 0;
1402044a 546 int current_row_offset;
844d1c9c 547 int column;
1fc22eb4
JD
548
549 elapsed = data->end - data->start;
550 maxcputime = elapsed * data->cpu_table->len / 100.0;
551
3b15348c
JD
552 if (cputopview[0].sort == 1)
553 g_ptr_array_sort(data->process_table, sort_by_cpu_desc);
554 else if (cputopview[1].sort == 1)
555 g_ptr_array_sort(data->process_table, sort_by_pid_desc);
556 else if (cputopview[2].sort == 1)
557 g_ptr_array_sort(data->process_table, sort_by_tid_desc);
558 else if (cputopview[3].sort == 1)
559 g_ptr_array_sort(data->process_table, sort_by_cpu_desc);
560 else
561 g_ptr_array_sort(data->process_table, sort_by_cpu_desc);
1fc22eb4
JD
562
563 set_window_title(center, "CPU Top");
564 wattron(center, A_BOLD);
844d1c9c 565 column = 1;
1402044a
JD
566 for (i = 0; i < 6; i++) {
567 if (toggle_virt < 0 && (i == 3 || i == 4)) {
568 continue;
569 }
41ff0645 570 if (cputopview[i].sort) {
844d1c9c 571 wattron(center, A_UNDERLINE);
41ff0645
JD
572 pref_current_sort = i;
573 }
844d1c9c
JD
574 mvwprintw(center, 1, column, cputopview[i].title);
575 wattroff(center, A_UNDERLINE);
576 column += 10;
577 }
1fc22eb4
JD
578 wattroff(center, A_BOLD);
579
dc8f04dd 580 max_center_lines = LINES - 5 - 7 - 1 - header_offset;
1fc22eb4
JD
581
582 /* iterate the process (thread) list */
583 for (i = list_offset; i < data->process_table->len &&
584 nblinedisplayed < max_center_lines; i++) {
585 tmp = g_ptr_array_index(data->process_table, i);
1402044a 586 current_row_offset = 1;
da4353bb 587 if (toggle_filter > 0 && !lookup_filter_tid_list(tmp->tid))
c8d75a13
JD
588 continue;
589
e15ed00a
JD
590 if (tmp->pid != tmp->tid)
591 if (toggle_threads == -1)
592 continue;
1fc22eb4 593
da4353bb 594 /* line */
1fc22eb4
JD
595 if (current_line == selected_line) {
596 selected_process = tmp;
1fc22eb4
JD
597 wattron(center, COLOR_PAIR(5));
598 mvwhline(center, current_line + header_offset, 1, ' ', COLS-3);
599 }
da4353bb
JD
600 /* filtered process */
601 if (process_selected(tmp)) {
602 if (current_line == selected_line)
603 wattron(center, COLOR_PAIR(7));
604 else
605 wattron(center, COLOR_PAIR(6));
606 }
1fc22eb4 607 /* CPU(%) */
1402044a
JD
608 mvwprintw(center, current_line + header_offset,
609 current_row_offset, "%1.2f",
1fc22eb4 610 tmp->totalcpunsec / maxcputime);
1402044a 611 current_row_offset += 10;
1fc22eb4 612 /* PID */
1402044a
JD
613 mvwprintw(center, current_line + header_offset,
614 current_row_offset, "%d", tmp->pid);
615 current_row_offset += 10;
6153ec12 616 /* TID */
1402044a
JD
617 mvwprintw(center, current_line + header_offset,
618 current_row_offset, "%d", tmp->tid);
619 current_row_offset += 10;
620 if (toggle_virt > 0) {
621 /* VPID */
622 mvwprintw(center, current_line + header_offset,
623 current_row_offset, "%d", tmp->vpid);
624 current_row_offset += 10;
625 /* VTID */
626 mvwprintw(center, current_line + header_offset,
627 current_row_offset, "%d", tmp->vtid);
628 current_row_offset += 10;
629 }
1fc22eb4 630 /* NAME */
1402044a
JD
631 mvwprintw(center, current_line + header_offset,
632 current_row_offset, "%s", tmp->comm);
da4353bb 633 wattroff(center, COLOR_PAIR(7));
635dc837 634 wattroff(center, COLOR_PAIR(6));
1fc22eb4
JD
635 wattroff(center, COLOR_PAIR(5));
636 nblinedisplayed++;
637 current_line++;
638 }
639}
640
641gint sort_perf(gconstpointer p1, gconstpointer p2, gpointer key)
642{
643 struct processtop *n1 = *(struct processtop **) p1;
644 struct processtop *n2 = *(struct processtop **) p2;
645
646 struct perfcounter *tmp1, *tmp2;
647 unsigned long totaln2 = 0;
648 unsigned long totaln1 = 0;
649
650 if (!key)
651 return 0;
652
653 tmp1 = g_hash_table_lookup(n1->perf, key);
654 if (!tmp1)
655 totaln1 = 0;
656 else
657 totaln1 = tmp1->count;
658
659 tmp2 = g_hash_table_lookup(n2->perf, key);
660 if (!tmp2)
661 totaln2 = 0;
662 else
663 totaln2 = tmp2->count;
664
665 if (totaln1 < totaln2)
666 return 1;
667 if (totaln1 == totaln2) {
668 totaln1 = n1->tid;
669 totaln2 = n2->tid;
670 if (totaln1 < totaln2)
671 return 1;
672 return -1;
673 }
674 return -1;
675}
676
677void print_key_title(char *key, int line)
678{
679 wattron(center, A_BOLD);
951303cc
JD
680 mvwprintw(center, line, 1, "%s", key);
681 mvwprintw(center, line, 30, " ");
1fc22eb4
JD
682 wattroff(center, A_BOLD);
683}
684
685void update_process_details()
686{
687 unsigned long elapsed;
688 double maxcputime;
d26643ed 689 struct processtop *tmp;
b093de8a
MB
690 struct files *file_tmp;
691 int i, j = 0;
69362330 692 char unit[4];
97514683 693 char filename_buf[COLS];
951303cc 694 int line = 1;
cc30e58d 695 int column;
32647247 696 GPtrArray *newfilearray = g_ptr_array_new();
951303cc
JD
697 GHashTableIter iter;
698 struct perfcounter *perfn1, *perfn2;
699 gpointer key;
1fc22eb4
JD
700
701 set_window_title(center, "Process details");
702
703
d26643ed
JD
704 tmp = find_process_tid(data,
705 selected_process->tid,
706 selected_process->comm);
1fc22eb4
JD
707 elapsed = data->end - data->start;
708 maxcputime = elapsed * data->cpu_table->len / 100.0;
709
951303cc 710 print_key_title("Name", line++);
d26643ed 711 wprintw(center, "%s", selected_process->comm);
951303cc 712 print_key_title("TID", line++);
d26643ed 713 wprintw(center, "%d", selected_process->tid);
1fc22eb4
JD
714 if (!tmp) {
715 print_key_title("Does not exit at this time", 3);
716 return;
717 }
718
951303cc 719 print_key_title("PID", line++);
1fc22eb4 720 wprintw(center, "%d", tmp->pid);
951303cc 721 print_key_title("PPID", line++);
1fc22eb4 722 wprintw(center, "%d", tmp->ppid);
1402044a
JD
723 print_key_title("VPID", line++);
724 wprintw(center, "%d", tmp->vpid);
725 print_key_title("VTID", line++);
726 wprintw(center, "%d", tmp->vtid);
727 print_key_title("VPPID", line++);
728 wprintw(center, "%d", tmp->vppid);
951303cc 729 print_key_title("CPU", line++);
1fc22eb4 730 wprintw(center, "%1.2f %%", tmp->totalcpunsec/maxcputime);
b093de8a 731
951303cc 732 print_key_title("READ B/s", line++);
69362330
JD
733 scale_unit(tmp->fileread, unit);
734 wprintw(center, "%s", unit);
b093de8a 735
951303cc 736 print_key_title("WRITE B/s", line++);
69362330
JD
737 scale_unit(tmp->filewrite, unit);
738 wprintw(center, "%s", unit);
b093de8a 739
951303cc
JD
740 g_hash_table_iter_init(&iter, global_perf_liszt);
741 while (g_hash_table_iter_next (&iter, &key, (gpointer) &perfn1)) {
742 print_key_title((char *) key, line++);
743 perfn2 = g_hash_table_lookup(tmp->perf, (char *) key);
744 wprintw(center, "%d", perfn2 ? perfn2->count : 0);
745 }
746 line++;
747
93d80d35 748 wattron(center, A_BOLD);
cc30e58d
JD
749 column = 1;
750 for (i = 0; i < 3; i++) {
41ff0645
JD
751 if (fileview[i].sort) {
752 pref_current_sort = i;
cc30e58d 753 wattron(center, A_UNDERLINE);
41ff0645 754 }
cc30e58d
JD
755 mvwprintw(center, line, column, fileview[i].title);
756 wattroff(center, A_UNDERLINE);
757 column += 10;
758 }
759 mvwprintw(center, line++, column, "FILENAME");
93d80d35
JD
760 wattroff(center, A_BOLD);
761
32647247
JD
762 /*
763 * since the process_files_table array could contain NULL file structures,
764 * and that the positions inside the array is important (it is the FD), we
765 * need to create a temporary array that we can sort.
766 */
767 for (i = 0; i < tmp->process_files_table->len; i++) {
768 file_tmp = g_ptr_array_index(tmp->process_files_table, i);
769 if (file_tmp)
770 g_ptr_array_add(newfilearray, file_tmp);
771 }
772
773 if (fileview[0].sort == 1)
774 g_ptr_array_sort(newfilearray, sort_by_file_fd_desc);
775 else if (fileview[1].sort == 1)
776 g_ptr_array_sort(newfilearray, sort_by_file_read_desc);
777 else if (fileview[2].sort == 1)
778 g_ptr_array_sort(newfilearray, sort_by_file_write_desc);
779 else
780 g_ptr_array_sort(newfilearray, sort_by_file_read_desc);
781
782 for (i = selected_line; i < newfilearray->len &&
951303cc 783 i < (selected_line + max_center_lines - line + 2); i++) {
32647247
JD
784 file_tmp = g_ptr_array_index(newfilearray, i);
785 if (!file_tmp)
786 continue;
951303cc 787 mvwprintw(center, line + j, 1, "%d", file_tmp->fd);
32647247 788 scale_unit(file_tmp->read, unit);
cc30e58d 789 mvwprintw(center, line + j, 11, "%s", unit);
32647247 790 scale_unit(file_tmp->write, unit);
cc30e58d 791 mvwprintw(center, line + j, 21, "%s", unit);
32647247 792 snprintf(filename_buf, COLS - 25, "%s", file_tmp->name);
cc30e58d 793 mvwprintw(center, line + j, 31, "%s", filename_buf);
32647247 794 j++;
b093de8a 795 }
32647247 796 g_ptr_array_free(newfilearray, TRUE);
1fc22eb4
JD
797}
798
799void update_perf()
800{
bb053abb 801 int i;
1fc22eb4
JD
802 int nblinedisplayed = 0;
803 int current_line = 0;
804 struct processtop *tmp;
805 int header_offset = 2;
806 int perf_row = 40;
807 struct perfcounter *perfn1, *perfn2;
1fc22eb4
JD
808 char *perf_key = NULL;
809 int value;
85db4618
JD
810 GHashTableIter iter;
811 gpointer key;
1fc22eb4
JD
812
813 set_window_title(center, "Perf Top");
814 wattron(center, A_BOLD);
815 mvwprintw(center, 1, 1, "PID");
816 mvwprintw(center, 1, 11, "TID");
817 mvwprintw(center, 1, 22, "NAME");
818
819 perf_row = 40;
0d91c12a 820 g_hash_table_iter_init(&iter, global_perf_liszt);
85db4618 821 while (g_hash_table_iter_next (&iter, &key, (gpointer) &perfn1)) {
1fc22eb4 822 if (perfn1->visible) {
41ff0645 823 if (perfn1->sort) {
bc958efa 824 /* pref_current_sort = i; */
41ff0645 825 wattron(center, A_UNDERLINE);
41ff0645 826 }
6419078d 827 /* + 5 to strip the "perf_" prefix */
1fc22eb4 828 mvwprintw(center, 1, perf_row, "%s",
6419078d 829 (char *) key + 5);
41ff0645 830 wattroff(center, A_UNDERLINE);
1fc22eb4
JD
831 perf_row += 20;
832 }
833 if (perfn1->sort) {
85db4618 834 perf_key = (char *) key;
1fc22eb4 835 }
1fc22eb4
JD
836 }
837 wattroff(center, A_BOLD);
838
839 g_ptr_array_sort_with_data(data->process_table, sort_perf, perf_key);
85db4618 840
91be6bb5 841 for (i = 0; i < data->process_table->len &&
1fc22eb4 842 nblinedisplayed < max_center_lines; i++) {
1fc22eb4 843 tmp = g_ptr_array_index(data->process_table, i);
c8d75a13 844
da4353bb 845 if (toggle_filter > 0 && !lookup_filter_tid_list(tmp->tid))
c8d75a13
JD
846 continue;
847
e15ed00a
JD
848 if (tmp->pid != tmp->tid)
849 if (toggle_threads == -1)
850 continue;
1fc22eb4 851
635dc837 852 if (process_selected(tmp)) {
da4353bb
JD
853 if (current_line == selected_line)
854 wattron(center, COLOR_PAIR(7));
855 else
856 wattron(center, COLOR_PAIR(6));
635dc837 857 }
1fc22eb4
JD
858 if (current_line == selected_line) {
859 selected_process = tmp;
860 wattron(center, COLOR_PAIR(5));
861 mvwhline(center, current_line + header_offset, 1, ' ', COLS-3);
862 }
863
864 mvwprintw(center, current_line + header_offset, 1, "%d", tmp->pid);
865 mvwprintw(center, current_line + header_offset, 11, "%d", tmp->tid);
866 mvwprintw(center, current_line + header_offset, 22, "%s", tmp->comm);
867
0d91c12a 868 g_hash_table_iter_init(&iter, global_perf_liszt);
1fc22eb4
JD
869
870 perf_row = 40;
85db4618 871 while (g_hash_table_iter_next (&iter, &key, (gpointer) &perfn1)) {
1fc22eb4 872 if (perfn1->visible) {
85db4618 873 perfn2 = g_hash_table_lookup(tmp->perf, (char *) key);
1fc22eb4
JD
874 if (perfn2)
875 value = perfn2->count;
876 else
877 value = 0;
b093de8a
MB
878 mvwprintw(center, current_line + header_offset,
879 perf_row, "%d", value);
1fc22eb4
JD
880 perf_row += 20;
881 }
1fc22eb4
JD
882 }
883
635dc837 884 wattroff(center, COLOR_PAIR(6));
1fc22eb4
JD
885 wattroff(center, COLOR_PAIR(5));
886 nblinedisplayed++;
887 current_line++;
888 }
889}
890
1fc22eb4
JD
891void update_iostream()
892{
893 int i;
894 int header_offset = 2;
895 struct processtop *tmp;
896 int nblinedisplayed = 0;
897 int current_line = 0;
b093de8a 898 int total = 0;
69362330 899 char unit[4];
41f5890b 900 int column;
1fc22eb4
JD
901
902 set_window_title(center, "IO Top");
903 wattron(center, A_BOLD);
69362330
JD
904 mvwprintw(center, 1, 1, "PID");
905 mvwprintw(center, 1, 11, "TID");
906 mvwprintw(center, 1, 22, "NAME");
41f5890b
JD
907 column = 40;
908 for (i = 0; i < 3; i++) {
41ff0645
JD
909 if (iostreamtopview[i].sort) {
910 pref_current_sort = i;
41f5890b 911 wattron(center, A_UNDERLINE);
41ff0645 912 }
41f5890b
JD
913 mvwprintw(center, 1, column, iostreamtopview[i].title);
914 wattroff(center, A_UNDERLINE);
915 column += 12;
916 }
1fc22eb4 917 wattroff(center, A_BOLD);
41f5890b 918 wattroff(center, A_UNDERLINE);
1fc22eb4 919
89f1e0d1
JD
920 if (iostreamtopview[0].sort == 1)
921 g_ptr_array_sort(data->process_table, sort_by_process_read_desc);
922 else if (iostreamtopview[1].sort == 1)
923 g_ptr_array_sort(data->process_table, sort_by_process_write_desc);
924 else if (iostreamtopview[2].sort == 1)
925 g_ptr_array_sort(data->process_table, sort_by_process_total_desc);
926 else
927 g_ptr_array_sort(data->process_table, sort_by_process_total_desc);
1fc22eb4
JD
928
929 for (i = list_offset; i < data->process_table->len &&
930 nblinedisplayed < max_center_lines; i++) {
931 tmp = g_ptr_array_index(data->process_table, i);
c8d75a13 932
da4353bb 933 if (toggle_filter > 0 && !lookup_filter_tid_list(tmp->tid))
c8d75a13
JD
934 continue;
935
e15ed00a
JD
936 if (tmp->pid != tmp->tid)
937 if (toggle_threads == -1)
938 continue;
1fc22eb4 939
635dc837 940 if (process_selected(tmp)) {
da4353bb
JD
941 if (current_line == selected_line)
942 wattron(center, COLOR_PAIR(7));
943 else
944 wattron(center, COLOR_PAIR(6));
635dc837 945 }
1fc22eb4
JD
946 if (current_line == selected_line) {
947 selected_process = tmp;
1fc22eb4
JD
948 wattron(center, COLOR_PAIR(5));
949 mvwhline(center, current_line + header_offset, 1, ' ', COLS-3);
950 }
69362330
JD
951 /* TGID */
952 mvwprintw(center, current_line + header_offset, 1, "%d", tmp->pid);
953 /* PID */
954 mvwprintw(center, current_line + header_offset, 11, "%d", tmp->tid);
955 /* NAME */
956 mvwprintw(center, current_line + header_offset, 22, "%s", tmp->comm);
b093de8a 957
1fc22eb4 958 /* READ (bytes/sec) */
69362330
JD
959 scale_unit(tmp->fileread, unit);
960 mvwprintw(center, current_line + header_offset, 40, "%s", unit);
1fc22eb4
JD
961
962 /* WRITE (bytes/sec) */
69362330
JD
963 scale_unit(tmp->filewrite, unit);
964 mvwprintw(center, current_line + header_offset, 52, "%s", unit);
1fc22eb4
JD
965
966 /* TOTAL STREAM */
b093de8a
MB
967 total = tmp->totalfileread + tmp->totalfilewrite;
968
69362330
JD
969 scale_unit(total, unit);
970 mvwprintw(center, current_line + header_offset, 64, "%s", unit);
b093de8a 971
635dc837 972 wattroff(center, COLOR_PAIR(6));
1fc22eb4
JD
973 wattroff(center, COLOR_PAIR(5));
974 nblinedisplayed++;
975 current_line++;
976 }
977}
978
979void update_current_view()
980{
981 sem_wait(&update_display_sem);
982 if (!data)
983 return;
984 update_header();
985
986 werase(center);
987 box(center, 0, 0);
988 switch (current_view) {
989 case cpu:
990 update_cputop_display();
991 break;
992 case perf:
993 update_perf();
994 break;
995 case process_details:
996 update_process_details();
997 break;
1fc22eb4
JD
998 case iostream:
999 update_iostream();
1000 break;
1001 case tree:
1002 update_cputop_display();
1003 break;
fbbda4da
JD
1004 case kprobes:
1005 update_kprobes_display();
1006 break;
1fc22eb4
JD
1007 default:
1008 break;
1009 }
1010 update_panels();
1011 doupdate();
1012 sem_post(&update_display_sem);
1013}
1014
41ff0645
JD
1015void update_process_detail_sort(int *line_selected)
1016{
1017 int i;
1018 int size;
1019
1020 size = 3;
1021
1022 if (*line_selected > (size - 1))
1023 *line_selected = size - 1;
1024 else if (*line_selected < 0)
1025 *line_selected = 0;
1026
1027 if (fileview[*line_selected].sort == 1)
1028 fileview[*line_selected].reverse = 1;
1029 for (i = 0; i < size; i++)
1030 fileview[i].sort = 0;
1031 fileview[*line_selected].sort = 1;
1032}
1033
32647247
JD
1034void update_process_detail_pref(int *line_selected, int toggle_view, int toggle_sort)
1035{
1036 int i;
1037 int size;
1038
1039 if (!data)
1040 return;
1041 if (pref_panel_window) {
1042 del_panel(pref_panel);
1043 delwin(pref_panel_window);
1044 }
1045 size = 3;
1046
1047 pref_panel_window = create_window(size + 2, 30, 10, 10);
1048 pref_panel = new_panel(pref_panel_window);
1049
1050 werase(pref_panel_window);
1051 box(pref_panel_window, 0 , 0);
1052 set_window_title(pref_panel_window, "Process Detail Preferences ");
1053 wattron(pref_panel_window, A_BOLD);
1054 mvwprintw(pref_panel_window, size + 1, 1,
d2fd8c70 1055 " 's' : sort, space : toggle");
32647247
JD
1056 wattroff(pref_panel_window, A_BOLD);
1057
1058 if (*line_selected > (size - 1))
1059 *line_selected = size - 1;
41ff0645
JD
1060 else if (*line_selected < 0)
1061 *line_selected = 0;
32647247 1062 if (toggle_sort == 1) {
41ff0645 1063 update_process_detail_sort(line_selected);
32647247
JD
1064 update_current_view();
1065 }
1066
1067 for (i = 0; i < size; i++) {
1068 if (i == *line_selected) {
1069 wattron(pref_panel_window, COLOR_PAIR(5));
1070 mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2);
1071 }
1072 if (fileview[i].sort == 1)
1073 wattron(pref_panel_window, A_BOLD);
d33aae69 1074 mvwprintw(pref_panel_window, i + 1, 1, "[-] %s",
32647247
JD
1075 fileview[i].title);
1076 wattroff(pref_panel_window, A_BOLD);
1077 wattroff(pref_panel_window, COLOR_PAIR(5));
1078
1079 }
1080 update_panels();
1081 doupdate();
1082}
1083
41ff0645
JD
1084void update_iostream_sort(int *line_selected)
1085{
1086 int i;
1087 int size;
1088
1089 size = 3;
1090 if (*line_selected > (size - 1))
1091 *line_selected = size - 1;
1092 else if (*line_selected < 0)
1093 *line_selected = 0;
1094 if (iostreamtopview[*line_selected].sort == 1)
1095 iostreamtopview[*line_selected].reverse = 1;
1096 for (i = 0; i < size; i++)
1097 iostreamtopview[i].sort = 0;
1098 iostreamtopview[*line_selected].sort = 1;
1099
1100}
1101
89f1e0d1
JD
1102void update_iostream_pref(int *line_selected, int toggle_view, int toggle_sort)
1103{
1104 int i;
1105 int size;
1106
1107 if (!data)
1108 return;
1109 if (pref_panel_window) {
1110 del_panel(pref_panel);
1111 delwin(pref_panel_window);
1112 }
1113 size = 3;
1114
1115 pref_panel_window = create_window(size + 2, 30, 10, 10);
1116 pref_panel = new_panel(pref_panel_window);
1117
1118 werase(pref_panel_window);
1119 box(pref_panel_window, 0 , 0);
1120 set_window_title(pref_panel_window, "IOTop Preferences ");
1121 wattron(pref_panel_window, A_BOLD);
1122 mvwprintw(pref_panel_window, size + 1, 1,
d2fd8c70 1123 " 's' : sort, space : toggle");
89f1e0d1
JD
1124 wattroff(pref_panel_window, A_BOLD);
1125
1126 if (*line_selected > (size - 1))
1127 *line_selected = size - 1;
41ff0645
JD
1128 else if (*line_selected < 0)
1129 *line_selected = 0;
89f1e0d1 1130 if (toggle_sort == 1) {
41ff0645 1131 update_iostream_sort(line_selected);
89f1e0d1
JD
1132 update_current_view();
1133 }
1134
1135 for (i = 0; i < size; i++) {
1136 if (i == *line_selected) {
1137 wattron(pref_panel_window, COLOR_PAIR(5));
1138 mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2);
1139 }
1140 if (iostreamtopview[i].sort == 1)
1141 wattron(pref_panel_window, A_BOLD);
d33aae69 1142 mvwprintw(pref_panel_window, i + 1, 1, "[-] %s",
89f1e0d1
JD
1143 iostreamtopview[i].title);
1144 wattroff(pref_panel_window, A_BOLD);
1145 wattroff(pref_panel_window, COLOR_PAIR(5));
1146
1147 }
1148 update_panels();
1149 doupdate();
1150}
1151
41ff0645
JD
1152void update_cpu_sort(int *line_selected)
1153{
1154 int i;
1155 int size = 3;
1156
1157 if (*line_selected > (size - 1))
1158 *line_selected = size - 1;
1159 else if (*line_selected < 0)
1160 *line_selected = 0;
1161
1162 /* special case, we don't support sorting by procname for now */
1163 if (*line_selected != 3) {
1164 if (cputopview[*line_selected].sort == 1)
1165 cputopview[*line_selected].reverse = 1;
1166 for (i = 0; i < size; i++)
1167 cputopview[i].sort = 0;
1168 cputopview[*line_selected].sort = 1;
1169 }
1170}
1171
3b15348c
JD
1172void update_cpu_pref(int *line_selected, int toggle_view, int toggle_sort)
1173{
1174 int i;
1175 int size;
1176
1177 if (!data)
1178 return;
1179 if (pref_panel_window) {
1180 del_panel(pref_panel);
1181 delwin(pref_panel_window);
1182 }
1183 size = 4;
1184
1185 pref_panel_window = create_window(size + 2, 30, 10, 10);
1186 pref_panel = new_panel(pref_panel_window);
1187
1188 werase(pref_panel_window);
1189 box(pref_panel_window, 0 , 0);
1190 set_window_title(pref_panel_window, "CPUTop Preferences ");
1191 wattron(pref_panel_window, A_BOLD);
1192 mvwprintw(pref_panel_window, size + 1, 1,
d2fd8c70 1193 " 's' : sort, space : toggle");
3b15348c
JD
1194 wattroff(pref_panel_window, A_BOLD);
1195
89f1e0d1
JD
1196 if (*line_selected > (size - 1))
1197 *line_selected = size - 1;
41ff0645
JD
1198 else if (*line_selected < 0)
1199 *line_selected = 0;
3b15348c 1200 if (toggle_sort == 1) {
41ff0645
JD
1201 update_cpu_sort(line_selected);
1202 update_current_view();
3b15348c
JD
1203 }
1204
89f1e0d1 1205 for (i = 0; i < size; i++) {
3b15348c
JD
1206 if (i == *line_selected) {
1207 wattron(pref_panel_window, COLOR_PAIR(5));
1208 mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2);
1209 }
1210 if (cputopview[i].sort == 1)
1211 wattron(pref_panel_window, A_BOLD);
d33aae69 1212 mvwprintw(pref_panel_window, i + 1, 1, "[-] %s",
3b15348c
JD
1213 cputopview[i].title);
1214 wattroff(pref_panel_window, A_BOLD);
1215 wattroff(pref_panel_window, COLOR_PAIR(5));
1216
1217 }
1218 update_panels();
1219 doupdate();
1220}
1221
41ff0645
JD
1222void update_perf_sort(int *line_selected)
1223{
1224 int i;
1225 struct perfcounter *perf;
1226 GList *perflist;
1227 int size;
1228
1229 size = g_hash_table_size(global_perf_liszt);
1230 if (*line_selected > (size - 1))
1231 *line_selected = size - 1;
1232 else if (*line_selected < 0)
1233 *line_selected = 0;
1234
1235 i = 0;
1236 perflist = g_list_first(g_hash_table_get_keys(global_perf_liszt));
1237 while (perflist) {
1238 perf = g_hash_table_lookup(global_perf_liszt, perflist->data);
1239 if (i != *line_selected)
1240 perf->sort = 0;
1241 else
1242 perf->sort = 1;
1243 i++;
1244 perflist = g_list_next(perflist);
1245 }
1246}
1247
3b15348c 1248void update_perf_pref(int *line_selected, int toggle_view, int toggle_sort)
1fc22eb4 1249{
1e05f0ae
JD
1250 int i;
1251 struct perfcounter *perf;
1252 GList *perflist;
1fc22eb4 1253 int size;
1e05f0ae 1254
1fc22eb4
JD
1255 if (!data)
1256 return;
0d91c12a
JD
1257 if (pref_panel_window) {
1258 del_panel(pref_panel);
1259 delwin(pref_panel_window);
1fc22eb4 1260 }
0d91c12a 1261 size = g_hash_table_size(global_perf_liszt);
1e05f0ae 1262
0d91c12a
JD
1263 pref_panel_window = create_window(size + 2, 30, 10, 10);
1264 pref_panel = new_panel(pref_panel_window);
1fc22eb4 1265
0d91c12a
JD
1266 werase(pref_panel_window);
1267 box(pref_panel_window, 0 , 0);
1268 set_window_title(pref_panel_window, "Perf Preferences ");
1269 wattron(pref_panel_window, A_BOLD);
1270 mvwprintw(pref_panel_window, g_hash_table_size(global_perf_liszt) + 1, 1,
d2fd8c70 1271 " 's' : sort, space : toggle");
0d91c12a 1272 wattroff(pref_panel_window, A_BOLD);
1fc22eb4 1273
41ff0645
JD
1274 if (*line_selected > (size - 1))
1275 *line_selected = size - 1;
1276 else if (*line_selected < 0)
1277 *line_selected = 0;
1278
1fc22eb4 1279 if (toggle_sort == 1) {
41ff0645 1280 update_perf_sort(line_selected);
1fc22eb4
JD
1281 update_current_view();
1282 }
1283
1284 i = 0;
0d91c12a 1285 perflist = g_list_first(g_hash_table_get_keys(global_perf_liszt));
1fc22eb4 1286 while (perflist) {
0d91c12a 1287 perf = g_hash_table_lookup(global_perf_liszt, perflist->data);
3b15348c 1288 if (i == *line_selected && toggle_view == 1) {
1fc22eb4
JD
1289 perf->visible = perf->visible == 1 ? 0:1;
1290 update_current_view();
1291 }
3b15348c 1292 if (i == *line_selected) {
0d91c12a
JD
1293 wattron(pref_panel_window, COLOR_PAIR(5));
1294 mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2);
1fc22eb4
JD
1295 }
1296 if (perf->sort == 1)
0d91c12a
JD
1297 wattron(pref_panel_window, A_BOLD);
1298 mvwprintw(pref_panel_window, i + 1, 1, "[%c] %s",
1fc22eb4 1299 perf->visible == 1 ? 'x' : ' ',
b8a1df45 1300 (char *) perflist->data + 5);
0d91c12a
JD
1301 wattroff(pref_panel_window, A_BOLD);
1302 wattroff(pref_panel_window, COLOR_PAIR(5));
1fc22eb4
JD
1303 i++;
1304 perflist = g_list_next(perflist);
1305 }
1306 update_panels();
1307 doupdate();
1308}
1309
3b15348c 1310int update_preference_panel(int *line_selected, int toggle_view, int toggle_sort)
1fc22eb4 1311{
1e05f0ae
JD
1312 int ret = 0;
1313
0d91c12a
JD
1314 switch(current_view) {
1315 case perf:
3b15348c
JD
1316 update_perf_pref(line_selected, toggle_view, toggle_sort);
1317 break;
1318 case cpu:
1319 update_cpu_pref(line_selected, toggle_view, toggle_sort);
0d91c12a 1320 break;
89f1e0d1
JD
1321 case iostream:
1322 update_iostream_pref(line_selected, toggle_view, toggle_sort);
1323 break;
32647247
JD
1324 case process_details:
1325 update_process_detail_pref(line_selected, toggle_view, toggle_sort);
1326 break;
0d91c12a 1327 default:
1e05f0ae 1328 ret = -1;
0d91c12a
JD
1329 break;
1330 }
1e05f0ae
JD
1331
1332 return ret;
0d91c12a
JD
1333}
1334
41ff0645
JD
1335int update_sort(int *line_selected)
1336{
1337 int ret = 0;
1338
1339 switch(current_view) {
1340 case perf:
1341 update_perf_sort(line_selected);
1342 break;
1343 case cpu:
1344 update_cpu_sort(line_selected);
1345 break;
1346 case iostream:
1347 update_iostream_sort(line_selected);
1348 break;
1349 case process_details:
1350 update_process_detail_sort(line_selected);
1351 break;
1352 default:
1353 ret = -1;
1354 break;
1355 }
1356
1357 return ret;
1358}
1359
1360
0d91c12a
JD
1361void toggle_pref_panel(void)
1362{
1e05f0ae
JD
1363 int ret;
1364
0d91c12a
JD
1365 if (pref_panel_visible) {
1366 hide_panel(pref_panel);
1367 pref_panel_visible = 0;
1fc22eb4 1368 } else {
3b15348c 1369 ret = update_preference_panel(&pref_line_selected, 0, 0);
1e05f0ae
JD
1370 if (ret < 0)
1371 return;
0d91c12a
JD
1372 show_panel(pref_panel);
1373 pref_panel_visible = 1;
1fc22eb4
JD
1374 }
1375 update_panels();
1376 doupdate();
1377}
1378
1379void display(unsigned int index)
1380{
1381 last_display_index = index;
1382 currently_displayed_index = index;
1383 data = g_ptr_array_index(copies, index);
1384 if (!data)
1385 return;
1386 max_elements = data->process_table->len;
1387 update_current_view();
1388 update_footer();
1389 update_panels();
1390 doupdate();
1391}
1392
1393void pause_display()
1394{
1395 toggle_pause = 1;
1396 print_log("Pause");
1397 sem_wait(&pause_sem);
1398}
1399
1400void resume_display()
1401{
1402 toggle_pause = -1;
1403 print_log("Resume");
1404 sem_post(&pause_sem);
1405}
1406
1407void *handle_keyboard(void *p)
1408{
1409 int ch;
1410 while((ch = getch())) {
1411 switch(ch) {
1412 /* Move the cursor and scroll */
8c05e516 1413 case 'j':
1fc22eb4 1414 case KEY_DOWN:
0d91c12a 1415 if (pref_panel_visible) {
3b15348c
JD
1416 pref_line_selected++;
1417 update_preference_panel(&pref_line_selected, 0, 0);
1fc22eb4
JD
1418 } else {
1419 if (selected_line < (max_center_lines - 1) &&
1420 selected_line < max_elements - 1) {
1421 selected_line++;
1422 selected_in_list++;
1423 } else if (selected_in_list < (max_elements - 1)
1424 && (list_offset < (max_elements - max_center_lines))) {
1425 selected_in_list++;
1426 list_offset++;
1427 }
1428 update_current_view();
1429 }
1430 break;
1431 case KEY_NPAGE:
1fc22eb4 1432 break;
8c05e516 1433 case 'k':
1fc22eb4 1434 case KEY_UP:
0d91c12a 1435 if (pref_panel_visible) {
3b15348c
JD
1436 if (pref_line_selected > 0)
1437 pref_line_selected--;
1438 update_preference_panel(&pref_line_selected, 0, 0);
1fc22eb4
JD
1439 } else {
1440 if (selected_line > 0) {
1441 selected_line--;
1442 selected_in_list--;
1443 } else if (selected_in_list > 0 && list_offset > 0) {
1444 selected_in_list--;
1445 list_offset--;
1446 }
1447 update_current_view();
1448 }
1449 break;
1450 case KEY_PPAGE:
1fc22eb4
JD
1451 break;
1452
1453 /* Navigate the history with arrows */
1454 case KEY_LEFT:
1455 if (currently_displayed_index > 0) {
1456 currently_displayed_index--;
1457 print_log("Going back in time");
1458 } else {
1459 print_log("Cannot rewind, last data is already displayed");
1460 }
1461 data = g_ptr_array_index(copies, currently_displayed_index);
1462 max_elements = data->process_table->len;
1463
1464 /* we force to pause the display when moving in time */
1465 if (toggle_pause < 0)
1466 pause_display();
1467
1468 update_current_view();
1469 update_footer();
1470 break;
1471 case KEY_RIGHT:
1472 if (currently_displayed_index < last_display_index) {
1473 currently_displayed_index++;
1474 print_log("Going forward in time");
1475 data = g_ptr_array_index(copies, currently_displayed_index);
1476 max_elements = data->process_table->len;
1477 update_current_view();
1478 update_footer();
1479 } else {
1480 print_log("Manually moving forward");
1481 sem_post(&timer);
3e59e768
JD
1482 if (toggle_pause > 0) {
1483 sem_post(&pause_sem);
1484 update_current_view();
1485 sem_wait(&pause_sem);
1486 }
1fc22eb4
JD
1487 }
1488
1489 break;
1490 case ' ':
0d91c12a 1491 if (pref_panel_visible) {
3b15348c 1492 update_preference_panel(&pref_line_selected, 1, 0);
635dc837
JD
1493 } else {
1494 update_selected_processes();
da4353bb
JD
1495 if (toggle_filter > 0) {
1496 max_elements = g_hash_table_size(global_filter_list);
1497 fprintf(stderr, "select : %d, max : %d\n",
1498 selected_line, max_elements);
1499 if (selected_line >= max_elements)
1500 selected_line = max_elements - 1;
1501 }
635dc837
JD
1502 update_current_view();
1503 }
1fc22eb4
JD
1504 break;
1505 case 's':
0d91c12a 1506 if (pref_panel_visible)
3b15348c 1507 update_preference_panel(&pref_line_selected, 0, 1);
1fc22eb4 1508 break;
41ff0645 1509 case '>':
bc958efa
JD
1510 /* perf uses a hashtable, it is ordered backward */
1511 if (current_view == perf) {
1512 pref_current_sort--;
1513 } else if (!pref_panel_visible) {
41ff0645 1514 pref_current_sort++;
41ff0645 1515 }
bc958efa
JD
1516 update_sort(&pref_current_sort);
1517 update_current_view();
41ff0645
JD
1518 break;
1519 case '<':
bc958efa
JD
1520 /* perf uses a hashtable, it is ordered backward */
1521 if (current_view == perf) {
1522 pref_current_sort++;
1523 } else if (!pref_panel_visible) {
1524 pref_current_sort--;
41ff0645 1525 }
bc958efa
JD
1526 update_sort(&pref_current_sort);
1527 update_current_view();
41ff0645 1528 break;
1fc22eb4
JD
1529
1530 case 13: /* FIXME : KEY_ENTER ?? */
d2fd8c70
JD
1531 if (pref_panel_visible)
1532 break;
041aa219
JD
1533 if (current_view != process_details) {
1534 previous_view = current_view;
1fc22eb4 1535 current_view = process_details;
041aa219
JD
1536 } else {
1537 current_view = previous_view;
1538 previous_view = process_details;
1fc22eb4 1539 }
7d9ea41a 1540 selected_line = 0;
1fc22eb4
JD
1541 update_current_view();
1542 break;
1543
1544 case KEY_F(1):
3b15348c
JD
1545 if (pref_panel_visible)
1546 toggle_pref_panel();
1fc22eb4 1547 current_view = cpu;
af54ebcf 1548 selected_line = 0;
1fc22eb4
JD
1549 update_current_view();
1550 break;
1551 case KEY_F(2):
3b15348c
JD
1552 if (pref_panel_visible)
1553 toggle_pref_panel();
1fc22eb4 1554 current_view = cpu;
af54ebcf 1555 selected_line = 0;
1fc22eb4
JD
1556 update_current_view();
1557 break;
1558 case KEY_F(3):
3b15348c
JD
1559 if (pref_panel_visible)
1560 toggle_pref_panel();
1fc22eb4 1561 current_view = perf;
af54ebcf 1562 selected_line = 0;
1fc22eb4
JD
1563 update_current_view();
1564 break;
1565 case KEY_F(4):
3b15348c
JD
1566 if (pref_panel_visible)
1567 toggle_pref_panel();
1fc22eb4 1568 current_view = iostream;
af54ebcf 1569 selected_line = 0;
1fc22eb4
JD
1570 update_current_view();
1571 break;
fbbda4da
JD
1572 case KEY_F(5):
1573 if (pref_panel_visible)
1574 toggle_pref_panel();
1575 current_view = kprobes;
1576 selected_line = 0;
1577 update_current_view();
1578 break;
1fc22eb4
JD
1579 case KEY_F(10):
1580 case 'q':
1581 reset_ncurses();
ae9e85c7
JD
1582 /* exit keyboard thread */
1583 pthread_exit(0);
1fc22eb4 1584 break;
da4353bb
JD
1585 case 'f':
1586 toggle_filter *= -1;
1587 selected_line = 0;
1588 if (toggle_filter > 0)
1589 max_elements = g_hash_table_size(global_filter_list);
1590 else
1591 max_elements = data->process_table->len;
1592 update_current_view();
1593 break;
1fc22eb4
JD
1594 case 't':
1595 toggle_threads *= -1;
1596 update_current_view();
1597 break;
1598 case 'p':
1599 if (toggle_pause < 0) {
1600 pause_display();
1601 } else {
1602 resume_display();
1603 }
33572a17 1604 break;
f9ff6939 1605 case 'r':
0d91c12a 1606 toggle_pref_panel();
1fc22eb4 1607 break;
1402044a
JD
1608 case 'v':
1609 toggle_virt *= -1;
1610 update_current_view();
1611 break;
d2fd8c70
JD
1612 /* ESCAPE, but slow to process, don't know why */
1613 case 27:
1614 if (pref_panel_visible)
1615 toggle_pref_panel();
1616 else if (current_view == process_details) {
1617 current_view = previous_view;
1618 previous_view = process_details;
1619 }
1620 update_current_view();
1621 break;
1fc22eb4 1622 default:
b093de8a
MB
1623 if (data)
1624 update_current_view();
1fc22eb4
JD
1625 break;
1626 }
1627 update_footer();
1628 }
1629 return NULL;
1630}
1631
89f1e0d1
JD
1632void init_view_headers()
1633{
1634 cputopview[0].title = strdup("CPU(%)");
1635 cputopview[0].sort = 1;
6153ec12
JD
1636 cputopview[1].title = strdup("PID");
1637 cputopview[2].title = strdup("TID");
1402044a
JD
1638 cputopview[3].title = strdup("VPID");
1639 cputopview[4].title = strdup("VTID");
1640 cputopview[5].title = strdup("NAME");
89f1e0d1
JD
1641
1642 iostreamtopview[0].title = strdup("R (B/sec)");
1643 iostreamtopview[1].title = strdup("W (B/sec)");
1644 iostreamtopview[2].title = strdup("Total (B)");
1645 iostreamtopview[2].sort = 1;
32647247
JD
1646
1647 fileview[0].title = strdup("FD");
1648 fileview[1].title = strdup("READ");
1649 fileview[1].sort = 1;
1650 fileview[2].title = strdup("WRITE");
246d5992
JD
1651
1652 kprobeview[0].title = strdup("NAME");
1653 kprobeview[1].title = strdup("HIT");
1654 kprobeview[1].sort = 1;
89f1e0d1
JD
1655}
1656
1fc22eb4
JD
1657void init_ncurses()
1658{
1659 sem_init(&update_display_sem, 0, 1);
89f1e0d1 1660 init_view_headers();
1fc22eb4
JD
1661 init_screen();
1662
dc8f04dd
JD
1663 header = create_window(5, COLS - 1, 0, 0);
1664 center = create_window(LINES - 5 - 7, COLS - 1, 5, 0);
1fc22eb4
JD
1665 status = create_window(MAX_LOG_LINES + 2, COLS - 1, LINES - 7, 0);
1666 footer = create_window(1, COLS - 1, LINES - 1, 0);
1667
1668 print_log("Starting display");
1669
1670 main_panel = new_panel(center);
1fc22eb4
JD
1671
1672 current_view = cpu;
1673
1674 basic_header();
1675 update_footer();
1676
1677 pthread_create(&keyboard_thread, NULL, handle_keyboard, (void *)NULL);
1678}
This page took 0.179307 seconds and 4 git commands to generate.