X-Git-Url: https://git.lttng.org/?p=lttngtop.git;a=blobdiff_plain;f=src%2Fcursesdisplay.c;h=49ec23ce6f8d72169abdc18af7ac33dd60902e61;hp=a2e3f275edd0c6bf528aad812bdd75e7551d3842;hb=84c36c18637e2b02dd9a91646065f90e02eca660;hpb=3b15348ccad727f0d6232af738efa96b20ebc56a diff --git a/src/cursesdisplay.c b/src/cursesdisplay.c index a2e3f27..49ec23c 100644 --- a/src/cursesdisplay.c +++ b/src/cursesdisplay.c @@ -65,7 +65,9 @@ GPtrArray *selected_processes; pthread_t keyboard_thread; -struct cputopview cputopview[4]; +struct header_view cputopview[4]; +struct header_view iostreamtopview[3]; +struct header_view fileview[3]; void reset_ncurses() { @@ -225,6 +227,8 @@ int process_selected(struct processtop *process) for (i = 0; i < selected_processes->len; i++) { stored_process = g_ptr_array_index(selected_processes, i); + if (!stored_process) + return 0; if (stored_process->tid == process->tid) return 1; } @@ -233,11 +237,21 @@ int process_selected(struct processtop *process) void update_selected_processes() { + int i; + struct processtop *stored_process; + if (process_selected(selected_process)) { - g_ptr_array_remove(selected_processes, selected_process); - print_log("Process removed"); + for (i = 0; i < selected_processes->len; i++) { + stored_process = g_ptr_array_index(selected_processes, i); + if (!stored_process) + return; + if (stored_process->tid == selected_process->tid) + g_ptr_array_remove(selected_processes, + stored_process); + print_log("Process removed"); + } } else { - g_ptr_array_add(selected_processes, selected_process); + g_ptr_array_add(selected_processes, selected_process); print_log("Process added"); } } @@ -265,8 +279,8 @@ void update_footer() print_key(footer, "F4", "IOTop ", current_view == iostream); print_key(footer, "Enter", "Details ", current_view == process_details); print_key(footer, "Space", "Highlight ", 0); - print_key(footer, "q", "Quit | ", 0); - print_key(footer, "P", "Perf Pref ", 0); + print_key(footer, "q", "Quit ", 0); + print_key(footer, "r", "Pref ", 0); print_key(footer, "p", "Pause ", toggle_pause); wrefresh(footer); @@ -404,6 +418,99 @@ gint sort_by_pid_desc(gconstpointer p1, gconstpointer p2) return -1; } +gint sort_by_process_read_desc(gconstpointer p1, gconstpointer p2) +{ + struct processtop *n1 = *(struct processtop **)p1; + struct processtop *n2 = *(struct processtop **)p2; + unsigned long totaln1 = n1->fileread; + unsigned long totaln2 = n2->fileread; + + if (totaln1 < totaln2) + return 1; + if (totaln1 == totaln2) + return 0; + return -1; +} + +gint sort_by_process_write_desc(gconstpointer p1, gconstpointer p2) +{ + struct processtop *n1 = *(struct processtop **)p1; + struct processtop *n2 = *(struct processtop **)p2; + unsigned long totaln1 = n1->filewrite; + unsigned long totaln2 = n2->filewrite; + + if (totaln1 < totaln2) + return 1; + if (totaln1 == totaln2) + return 0; + return -1; +} + +gint sort_by_process_total_desc(gconstpointer p1, gconstpointer p2) +{ + struct processtop *n1 = *(struct processtop **)p1; + struct processtop *n2 = *(struct processtop **)p2; + unsigned long totaln1 = n1->filewrite + n1->fileread; + unsigned long totaln2 = n2->filewrite + n2->fileread; + + if (totaln1 < totaln2) + return 1; + if (totaln1 == totaln2) + return 0; + return -1; +} + +gint sort_by_file_read_desc(gconstpointer p1, gconstpointer p2) +{ + struct files *n1 = *(struct files **)p1; + struct files *n2 = *(struct files **)p2; + unsigned long totaln1; + unsigned long totaln2; + + totaln1 = n1->read; + totaln2 = n2->read; + + if (totaln1 < totaln2) + return 1; + if (totaln1 == totaln2) + return 0; + return -1; +} + +gint sort_by_file_write_desc(gconstpointer p1, gconstpointer p2) +{ + struct files *n1 = *(struct files **)p1; + struct files *n2 = *(struct files **)p2; + unsigned long totaln1; + unsigned long totaln2; + + totaln1 = n1->write; + totaln2 = n2->write; + + if (totaln1 < totaln2) + return 1; + if (totaln1 == totaln2) + return 0; + return -1; +} + +gint sort_by_file_fd_desc(gconstpointer p1, gconstpointer p2) +{ + struct files *n1 = *(struct files **)p1; + struct files *n2 = *(struct files **)p2; + unsigned long totaln1; + unsigned long totaln2; + + totaln1 = n1->fd; + totaln2 = n2->fd; + + if (totaln1 < totaln2) + return 1; + if (totaln1 == totaln2) + return 0; + return -1; +} + gint sort_by_cpu_group_by_threads_desc(gconstpointer p1, gconstpointer p2) { struct processtop *n1 = *(struct processtop **)p1; @@ -427,6 +534,7 @@ void update_cputop_display() double maxcputime; int nblinedisplayed = 0; int current_line = 0; + int column; elapsed = data->end - data->start; maxcputime = elapsed * data->cpu_table->len / 100.0; @@ -444,10 +552,14 @@ void update_cputop_display() set_window_title(center, "CPU Top"); wattron(center, A_BOLD); - mvwprintw(center, 1, 1, cputopview[0].title); - mvwprintw(center, 1, 12, cputopview[1].title); - mvwprintw(center, 1, 22, cputopview[2].title); - mvwprintw(center, 1, 32, cputopview[3].title); + column = 1; + for (i = 0; i < 4; i++) { + if (cputopview[i].sort) + wattron(center, A_UNDERLINE); + mvwprintw(center, 1, column, cputopview[i].title); + wattroff(center, A_UNDERLINE); + column += 10; + } wattroff(center, A_BOLD); max_center_lines = LINES - 5 - 7 - 1 - header_offset; @@ -457,7 +569,6 @@ void update_cputop_display() nblinedisplayed < max_center_lines; i++) { tmp = g_ptr_array_index(data->process_table, i); - /* FIXME : random segfault here */ if (process_selected(tmp)) { wattron(center, COLOR_PAIR(6)); mvwhline(center, current_line + header_offset, 1, ' ', COLS-3); @@ -471,11 +582,11 @@ void update_cputop_display() mvwprintw(center, current_line + header_offset, 1, "%1.2f", tmp->totalcpunsec / maxcputime); /* TGID */ - mvwprintw(center, current_line + header_offset, 12, "%d", tmp->pid); + mvwprintw(center, current_line + header_offset, 11, "%d", tmp->pid); /* PID */ - mvwprintw(center, current_line + header_offset, 22, "%d", tmp->tid); + mvwprintw(center, current_line + header_offset, 21, "%d", tmp->tid); /* NAME */ - mvwprintw(center, current_line + header_offset, 32, "%s", tmp->comm); + mvwprintw(center, current_line + header_offset, 31, "%s", tmp->comm); wattroff(center, COLOR_PAIR(6)); wattroff(center, COLOR_PAIR(5)); nblinedisplayed++; @@ -535,6 +646,7 @@ void update_process_details() int i, j = 0; char unit[4]; char filename_buf[COLS]; + GPtrArray *newfilearray = g_ptr_array_new(); set_window_title(center, "Process details"); @@ -576,20 +688,41 @@ void update_process_details() mvwprintw(center, 8, 24, "FILENAME"); wattroff(center, A_BOLD); - for (i = selected_line; i < tmp->process_files_table->len && + /* + * since the process_files_table array could contain NULL file structures, + * and that the positions inside the array is important (it is the FD), we + * need to create a temporary array that we can sort. + */ + for (i = 0; i < tmp->process_files_table->len; i++) { + file_tmp = g_ptr_array_index(tmp->process_files_table, i); + if (file_tmp) + g_ptr_array_add(newfilearray, file_tmp); + } + + if (fileview[0].sort == 1) + g_ptr_array_sort(newfilearray, sort_by_file_fd_desc); + else if (fileview[1].sort == 1) + g_ptr_array_sort(newfilearray, sort_by_file_read_desc); + else if (fileview[2].sort == 1) + g_ptr_array_sort(newfilearray, sort_by_file_write_desc); + else + g_ptr_array_sort(newfilearray, sort_by_file_read_desc); + + for (i = selected_line; i < newfilearray->len && i < (selected_line + max_center_lines - 7); i++) { - file_tmp = get_file(tmp, i); - if (file_tmp != NULL) { - mvwprintw(center, 9 + j, 1, "%d", i); - scale_unit(file_tmp->read, unit); - mvwprintw(center, 9 + j, 10, "%s", unit); - scale_unit(file_tmp->write, unit); - mvwprintw(center, 9 + j, 17, "%s", unit); - snprintf(filename_buf, COLS - 25, "%s", file_tmp->name); - mvwprintw(center, 9 + j, 24, "%s", filename_buf); - j++; - } + file_tmp = g_ptr_array_index(newfilearray, i); + if (!file_tmp) + continue; + mvwprintw(center, 9 + j, 1, "%d", file_tmp->fd); + scale_unit(file_tmp->read, unit); + mvwprintw(center, 9 + j, 10, "%s", unit); + scale_unit(file_tmp->write, unit); + mvwprintw(center, 9 + j, 17, "%s", unit); + snprintf(filename_buf, COLS - 25, "%s", file_tmp->name); + mvwprintw(center, 9 + j, 24, "%s", filename_buf); + j++; } + g_ptr_array_free(newfilearray, TRUE); } void update_perf() @@ -671,21 +804,6 @@ void update_perf() } } -gint sort_by_ret_desc(gconstpointer p1, gconstpointer p2) -{ - struct processtop *n1 = *(struct processtop **)p1; - struct processtop *n2 = *(struct processtop **)p2; - - unsigned long totaln1 = n1->totalfileread + n1->totalfilewrite; - unsigned long totaln2 = n2->totalfileread + n2->totalfilewrite; - - if (totaln1 < totaln2) - return 1; - if (totaln1 == totaln2) - return 0; - return -1; -} - void update_iostream() { int i; @@ -706,7 +824,14 @@ void update_iostream() mvwprintw(center, 1, 64, "Total"); wattroff(center, A_BOLD); - g_ptr_array_sort(data->process_table, sort_by_ret_desc); + if (iostreamtopview[0].sort == 1) + g_ptr_array_sort(data->process_table, sort_by_process_read_desc); + else if (iostreamtopview[1].sort == 1) + g_ptr_array_sort(data->process_table, sort_by_process_write_desc); + else if (iostreamtopview[2].sort == 1) + g_ptr_array_sort(data->process_table, sort_by_process_total_desc); + else + g_ptr_array_sort(data->process_table, sort_by_process_total_desc); for (i = list_offset; i < data->process_table->len && nblinedisplayed < max_center_lines; i++) { @@ -782,6 +907,110 @@ void update_current_view() sem_post(&update_display_sem); } +void update_process_detail_pref(int *line_selected, int toggle_view, int toggle_sort) +{ + int i; + int size; + + if (!data) + return; + if (pref_panel_window) { + del_panel(pref_panel); + delwin(pref_panel_window); + } + size = 3; + + pref_panel_window = create_window(size + 2, 30, 10, 10); + pref_panel = new_panel(pref_panel_window); + + werase(pref_panel_window); + box(pref_panel_window, 0 , 0); + set_window_title(pref_panel_window, "Process Detail Preferences "); + wattron(pref_panel_window, A_BOLD); + mvwprintw(pref_panel_window, size + 1, 1, + " 's' : sort, space : toggle"); + wattroff(pref_panel_window, A_BOLD); + + if (*line_selected > (size - 1)) + *line_selected = size - 1; + if (toggle_sort == 1) { + if (fileview[*line_selected].sort == 1) + fileview[*line_selected].reverse = 1; + for (i = 0; i < size; i++) + fileview[i].sort = 0; + fileview[*line_selected].sort = 1; + update_current_view(); + } + + for (i = 0; i < size; i++) { + if (i == *line_selected) { + wattron(pref_panel_window, COLOR_PAIR(5)); + mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2); + } + if (fileview[i].sort == 1) + wattron(pref_panel_window, A_BOLD); + mvwprintw(pref_panel_window, i + 1, 1, "[-] %s", + fileview[i].title); + wattroff(pref_panel_window, A_BOLD); + wattroff(pref_panel_window, COLOR_PAIR(5)); + + } + update_panels(); + doupdate(); +} + +void update_iostream_pref(int *line_selected, int toggle_view, int toggle_sort) +{ + int i; + int size; + + if (!data) + return; + if (pref_panel_window) { + del_panel(pref_panel); + delwin(pref_panel_window); + } + size = 3; + + pref_panel_window = create_window(size + 2, 30, 10, 10); + pref_panel = new_panel(pref_panel_window); + + werase(pref_panel_window); + box(pref_panel_window, 0 , 0); + set_window_title(pref_panel_window, "IOTop Preferences "); + wattron(pref_panel_window, A_BOLD); + mvwprintw(pref_panel_window, size + 1, 1, + " 's' : sort, space : toggle"); + wattroff(pref_panel_window, A_BOLD); + + if (*line_selected > (size - 1)) + *line_selected = size - 1; + if (toggle_sort == 1) { + if (iostreamtopview[*line_selected].sort == 1) + iostreamtopview[*line_selected].reverse = 1; + for (i = 0; i < size; i++) + iostreamtopview[i].sort = 0; + iostreamtopview[*line_selected].sort = 1; + update_current_view(); + } + + for (i = 0; i < size; i++) { + if (i == *line_selected) { + wattron(pref_panel_window, COLOR_PAIR(5)); + mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2); + } + if (iostreamtopview[i].sort == 1) + wattron(pref_panel_window, A_BOLD); + mvwprintw(pref_panel_window, i + 1, 1, "[-] %s", + iostreamtopview[i].title); + wattroff(pref_panel_window, A_BOLD); + wattroff(pref_panel_window, COLOR_PAIR(5)); + + } + update_panels(); + doupdate(); +} + void update_cpu_pref(int *line_selected, int toggle_view, int toggle_sort) { int i; @@ -803,31 +1032,31 @@ void update_cpu_pref(int *line_selected, int toggle_view, int toggle_sort) set_window_title(pref_panel_window, "CPUTop Preferences "); wattron(pref_panel_window, A_BOLD); mvwprintw(pref_panel_window, size + 1, 1, - " 's' to sort"); + " 's' : sort, space : toggle"); wattroff(pref_panel_window, A_BOLD); - if (*line_selected > 3) - *line_selected = 3; + if (*line_selected > (size - 1)) + *line_selected = size - 1; if (toggle_sort == 1) { /* special case, we don't support sorting by procname for now */ if (*line_selected != 3) { if (cputopview[*line_selected].sort == 1) cputopview[*line_selected].reverse = 1; - for (i = 0; i < 4; i++) + for (i = 0; i < size; i++) cputopview[i].sort = 0; cputopview[*line_selected].sort = 1; update_current_view(); } } - for (i = 0; i < 4; i++) { + for (i = 0; i < size; i++) { if (i == *line_selected) { wattron(pref_panel_window, COLOR_PAIR(5)); mvwhline(pref_panel_window, i + 1, 1, ' ', 30 - 2); } if (cputopview[i].sort == 1) wattron(pref_panel_window, A_BOLD); - mvwprintw(pref_panel_window, i + 1, 1, "[x] %s", + mvwprintw(pref_panel_window, i + 1, 1, "[-] %s", cputopview[i].title); wattroff(pref_panel_window, A_BOLD); wattroff(pref_panel_window, COLOR_PAIR(5)); @@ -860,7 +1089,7 @@ void update_perf_pref(int *line_selected, int toggle_view, int toggle_sort) set_window_title(pref_panel_window, "Perf Preferences "); wattron(pref_panel_window, A_BOLD); mvwprintw(pref_panel_window, g_hash_table_size(global_perf_liszt) + 1, 1, - " 's' to sort"); + " 's' : sort, space : toggle"); wattroff(pref_panel_window, A_BOLD); if (toggle_sort == 1) { @@ -915,6 +1144,12 @@ int update_preference_panel(int *line_selected, int toggle_view, int toggle_sort case cpu: update_cpu_pref(line_selected, toggle_view, toggle_sort); break; + case iostream: + update_iostream_pref(line_selected, toggle_view, toggle_sort); + break; + case process_details: + update_process_detail_pref(line_selected, toggle_view, toggle_sort); + break; default: ret = -1; break; @@ -975,6 +1210,7 @@ void *handle_keyboard(void *p) while((ch = getch())) { switch(ch) { /* Move the cursor and scroll */ + case 'j': case KEY_DOWN: if (pref_panel_visible) { pref_line_selected++; @@ -994,6 +1230,7 @@ void *handle_keyboard(void *p) break; case KEY_NPAGE: break; + case 'k': case KEY_UP: if (pref_panel_visible) { if (pref_line_selected > 0) @@ -1042,9 +1279,11 @@ void *handle_keyboard(void *p) } else { print_log("Manually moving forward"); sem_post(&timer); - /* we force to resume the refresh when moving forward */ - if (toggle_pause > 0) - resume_display(); + if (toggle_pause > 0) { + sem_post(&pause_sem); + update_current_view(); + sem_wait(&pause_sem); + } } break; @@ -1062,6 +1301,8 @@ void *handle_keyboard(void *p) break; case 13: /* FIXME : KEY_ENTER ?? */ + if (pref_panel_visible) + break; if (current_view != process_details) { previous_view = current_view; current_view = process_details; @@ -1115,9 +1356,19 @@ void *handle_keyboard(void *p) resume_display(); } break; - case 'P': + case 'r': toggle_pref_panel(); break; + /* ESCAPE, but slow to process, don't know why */ + case 27: + if (pref_panel_visible) + toggle_pref_panel(); + else if (current_view == process_details) { + current_view = previous_view; + previous_view = process_details; + } + update_current_view(); + break; default: if (data) update_current_view(); @@ -1128,10 +1379,30 @@ void *handle_keyboard(void *p) return NULL; } +void init_view_headers() +{ + cputopview[0].title = strdup("CPU(%)"); + cputopview[0].sort = 1; + cputopview[1].title = strdup("TGID"); + cputopview[2].title = strdup("PID"); + cputopview[3].title = strdup("NAME"); + + iostreamtopview[0].title = strdup("R (B/sec)"); + iostreamtopview[1].title = strdup("W (B/sec)"); + iostreamtopview[2].title = strdup("Total (B)"); + iostreamtopview[2].sort = 1; + + fileview[0].title = strdup("FD"); + fileview[1].title = strdup("READ"); + fileview[1].sort = 1; + fileview[2].title = strdup("WRITE"); +} + void init_ncurses() { selected_processes = g_ptr_array_new(); sem_init(&update_display_sem, 0, 1); + init_view_headers(); init_screen(); header = create_window(5, COLS - 1, 0, 0); @@ -1139,11 +1410,6 @@ void init_ncurses() status = create_window(MAX_LOG_LINES + 2, COLS - 1, LINES - 7, 0); footer = create_window(1, COLS - 1, LINES - 1, 0); - cputopview[0].title = strdup("CPU(%)"); - cputopview[0].sort = 1; - cputopview[1].title = strdup("TGID"); - cputopview[2].title = strdup("PID"); - cputopview[3].title = strdup("NAME"); print_log("Starting display"); main_panel = new_panel(center);