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