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