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