static int search_cb(search_t *search, search_event_t *evt, void *udata) { batch_decoder_t *bd = (batch_decoder_t *) udata; dict_t *d = search_factory_d2p(bd->sf)->dict; double delta = get_time_delta(bd); double frate = cmd_ln_int32_r(search_config(search), "-frate"); FILE *hypfh = NULL; void *val; if (hash_table_lookup(bd->hypfiles, search_name(search), &val) == 0) hypfh = val; else hypfh = stdout; fprintf(hypfh, "time delta %f ", delta); switch (evt->event) { case SEARCH_PARTIAL_RESULT: { int32 score; seg_iter_t *seg = search_seg_iter(search, &score); fprintf(hypfh, "partial: "); for (; seg; seg = seg_iter_next(seg)) { int sf, ef; seg_iter_times(seg, &sf, &ef); fprintf(hypfh, "%s:%.3f ", dict_basestr(d, seg_iter_wid(seg)), (double) ef / frate); } fprintf(hypfh, "(%s)\n", search_uttid(search)); break; } case SEARCH_START_UTT: fprintf(hypfh, "start %s\n", search_uttid(search)); break; case SEARCH_END_UTT: fprintf(hypfh, "end %s\n", search_uttid(search)); break; case SEARCH_FINAL_RESULT: { int32 score; seg_iter_t *seg = search_seg_iter(search, &score); fprintf(hypfh, "full: "); for (; seg; seg = seg_iter_next(seg)) { int sf, ef; seg_iter_times(seg, &sf, &ef); fprintf(hypfh, "%s:%.3f ", dict_basestr(d, seg_iter_wid(seg)), (double) ef / frate); } fprintf(hypfh, "(%s)\n", search_uttid(search)); break; } } return 0; }
/** * Copy wrapup. If "quiet" has not been specified, then * print a message to the curses screen about this thread being done. * * @param[in] fseg file segment descriptor. */ void copy_wrap(file_seg_t * fseg) { if (HAVE_OPT(QUIET)) return; pthread_mutex_lock(&tty_mutex); move(ENTRY_LINE + 1, 0); clrtoeol(); move(ENTRY_LINE, 0); clrtoeol(); printw("th %2d DONE - copied 0x%08X bytes in %lu seconds", fseg->idx, fseg->end - fseg->start, get_time_delta() / BILLION); refresh(); pthread_mutex_unlock(&tty_mutex); }
void sinsp_cursesui::handle_end_of_sample(sinsp_evt* evt, int32_t next_res) { m_datatable->flush(evt); // // It's time to refresh the data for this chart. // First of all, create the data for the chart // vector<sinsp_sample_row>* sample = m_datatable->get_sample(get_time_delta()); #ifndef NOCURSESUI if(!m_raw_output) { // // If the help page has been shown, don't update the screen // if(m_viewinfo_page != NULL || m_mainhelp_page != NULL) { return; } // // Now refresh the UI. // if(m_viz && !m_paused) { m_viz->update_data(sample); if(m_datatable->m_type == sinsp_table::TT_LIST && m_inspector->is_live()) { m_viz->follow_end(); } m_viz->render(true); } render(); } #endif // // If this is a trace file, check if we reached the end of the file. // Or, if we are in replay mode, wait for a key press before processing // the next sample. // if(!m_inspector->is_live()) { #ifndef NOCURSESUI if(!m_raw_output) { if(m_offline_replay) { while(getch() != ' ') { usleep(10000); } } } #endif } }
sysdig_table_action sinsp_cursesui::handle_textbox_input(int ch) { bool closing = false; string* str = NULL; bool handled = true; // // Pick the right string based on what we're doing // if(m_output_filtering) { str = &m_manual_filter; } else if(m_output_searching) { str = &m_manual_search_text; } else { if(m_search_caller_interface) { str = m_search_caller_interface->get_last_search_string(); } else { ASSERT(false); } } switch(ch) { case KEY_F(1): m_mainhelp_page = new curses_mainhelp_page(this); return STA_NONE; case KEY_F(2): m_is_filter_sysdig = !m_is_filter_sysdig; *str = ""; m_cursor_pos = 0; render(); return STA_NONE; case KEY_DOWN: case KEY_UP: case KEY_PPAGE: case KEY_NPAGE: if(m_spy_box != NULL) { m_spy_box->handle_input(ch); } else { m_viz->handle_input(ch); } return STA_NONE; case 27: // ESC *str = ""; if(m_spy_box != NULL) { m_spy_box->scroll_to(m_search_start_x, m_search_start_y); m_spy_box->up(); } // FALL THROUGH case '\n': case '\r': case KEY_ENTER: case 6: // CTRL+F case KEY_F(4): closing = true; curs_set(0); if(m_is_filter_sysdig && !m_output_searching) { if(*str != "") { sinsp_filter* f; try { f = new sinsp_filter(m_inspector, *str); } catch(sinsp_exception e) { // // Backup the cursor position // int cx, cy; getyx(stdscr, cy, cx); // // Print the error string // string wstr = "Invalid sysdig filter"; attrset(m_colors[sinsp_cursesui::FAILED_SEARCH]); mvprintw(m_screenh / 2, m_screenw / 2 - wstr.size() / 2, wstr.c_str()); // // Restore the cursor // attrset(m_colors[PANEL_HIGHLIGHT_FOCUS]); move(cy, cx); curs_set(1); closing = false; break; } delete f; } } break; case KEY_BACKSPACE: case 127: if(str->size() > 0) { m_cursor_pos--; move(m_screenh - 1, m_cursor_pos); addch(' '); move(m_screenh - 1, m_cursor_pos); *str = str->substr(0, str->size() - 1); if(str->size() < 2) { if(m_spy_box != NULL) { m_spy_box->scroll_to(m_search_start_x, m_search_start_y); } } break; } else { return STA_NONE; } case KEY_F(3): if(m_search_caller_interface) { if(m_search_caller_interface->on_search_next()) { render(); } else { string wstr = " NOT FOUND "; attrset(m_colors[sinsp_cursesui::FAILED_SEARCH]); mvprintw(m_screenh / 2, m_screenw / 2 - wstr.size() / 2, wstr.c_str()); render(); } } break; default: handled = false; break; } if(ch >= ' ' && ch <= '~') { addch(ch); *str += ch; m_cursor_pos++; } else { if(!handled) { return STA_NONE; } } if(m_output_filtering) { if(!m_is_filter_sysdig) { // // Update the filter in the datatable // m_datatable->set_freetext_filter(*str); // // Refresh the data and the visualization // m_viz->update_data(m_datatable->get_sample(get_time_delta()), true); m_viz->render(true); } } else if(m_output_searching) { sinsp_table_field* skey = m_datatable->search_in_sample(*str); if(skey != NULL) { int32_t selct = m_datatable->get_row_from_key(skey); m_viz->goto_row(selct); m_search_nomatch = false; } else { m_search_nomatch = true; m_viz->render(true); } } else { if(m_search_caller_interface) { if(m_search_caller_interface->on_search_key_pressed(*str)) { render(); } else { string wstr = " NOT FOUND "; attrset(m_colors[sinsp_cursesui::FAILED_SEARCH]); mvprintw(m_screenh / 2, m_screenw / 2 - wstr.size() / 2, wstr.c_str()); render(); } render(); } else { ASSERT(false); } } if(closing) { sysdig_table_action res = STA_NONE; if(m_is_filter_sysdig && !m_output_searching) { res = STA_SWITCH_VIEW; } m_search_nomatch = false; m_output_filtering = false; m_output_searching = false; m_search_caller_interface = NULL; render(); if(res != STA_NONE) { return res; } } return STA_NONE; }
/** * locking_reserve - reserve a slot in the buffer for an event. * @rchan: the channel * @slot_len: the length of the slot to reserve * @ts: variable that will receive the time the slot was reserved * @tsc: the timestamp counter associated with time * @err: receives the result flags * @interrupting: if this write is interrupting another, set to non-zero * * Returns pointer to the beginning of the reserved slot, NULL if error. * * The err value contains the result flags and is an ORed combination * of the following: * * RELAY_BUFFER_SWITCH_NONE - no buffer switch occurred * RELAY_EVENT_DISCARD_NONE - event should not be discarded * RELAY_BUFFER_SWITCH - buffer switch occurred * RELAY_EVENT_DISCARD - event should be discarded (all buffers are full) * RELAY_EVENT_TOO_LONG - event won't fit into even an empty buffer */ inline char * locking_reserve(struct rchan *rchan, u32 slot_len, struct timeval *ts, u32 *tsc, int *err, int *interrupting) { u32 buffers_ready; int bytes_written; *err = RELAY_BUFFER_SWITCH_NONE; if (slot_len >= rchan->buf_size) { *err = RELAY_WRITE_DISCARD | RELAY_WRITE_TOO_LONG; return NULL; } if (rchan->initialized == 0) { rchan->initialized = 1; get_timestamp(&rchan->buf_start_time, &rchan->buf_start_tsc, rchan); rchan->unused_bytes[0] = 0; bytes_written = rchan->callbacks->buffer_start( rchan->id, cur_write_pos(rchan), rchan->buf_id, rchan->buf_start_time, rchan->buf_start_tsc, using_tsc(rchan)); cur_write_pos(rchan) += bytes_written; *tsc = get_time_delta(ts, rchan); return cur_write_pos(rchan); } *tsc = get_time_delta(ts, rchan); if (in_progress_event_size(rchan)) { interrupted_pos(rchan) = cur_write_pos(rchan); cur_write_pos(rchan) = in_progress_event_pos(rchan) + in_progress_event_size(rchan) + interrupting_size(rchan); *interrupting = 1; } else { in_progress_event_pos(rchan) = cur_write_pos(rchan); in_progress_event_size(rchan) = slot_len; interrupting_size(rchan) = 0; } if (cur_write_pos(rchan) + slot_len > write_limit(rchan)) { if (atomic_read(&rchan->suspended) == 1) { in_progress_event_pos(rchan) = NULL; in_progress_event_size(rchan) = 0; interrupting_size(rchan) = 0; *err = RELAY_WRITE_DISCARD; return NULL; } buffers_ready = rchan->bufs_produced - rchan->bufs_consumed; if (buffers_ready == rchan->n_bufs - 1) { if (!mode_continuous(rchan)) { atomic_set(&rchan->suspended, 1); in_progress_event_pos(rchan) = NULL; in_progress_event_size(rchan) = 0; interrupting_size(rchan) = 0; get_timestamp(ts, tsc, rchan); switch_buffers(*ts, *tsc, rchan, 0, 0, 1); recalc_time_delta(ts, tsc, rchan); rchan->half_switch = 1; cur_write_pos(rchan) = write_buf_end(rchan) - 1; *err = RELAY_BUFFER_SWITCH | RELAY_WRITE_DISCARD; return NULL; } } get_timestamp(ts, tsc, rchan); switch_buffers(*ts, *tsc, rchan, 0, 0, 0); recalc_time_delta(ts, tsc, rchan); *err = RELAY_BUFFER_SWITCH; } return cur_write_pos(rchan); }
static int batch_decoder_decode_adc(batch_decoder_t *bd, FILE *infh, int sf, int ef, alignment_t *al) { featbuf_t *fb = search_factory_featbuf(bd->sf); float32 samprate = cmd_ln_float32_r(bd->config, "-samprate"); int32 frate = cmd_ln_int32_r(bd->config, "-frate"); int16 buf[512]; if (ef != -1) { ef = (int32) (((ef - sf) * samprate / frate) + (samprate * cmd_ln_float32_r(bd->config, "-wlen"))); } sf = (int32) (sf * (samprate / frate)); fseek(infh, cmd_ln_int32_r(bd->config, "-adchdr") + sf * sizeof(int16), SEEK_SET); if (al) { alignment_iter_t *itor; double starttime = 0.0; for (itor = alignment_words(al); itor; itor = alignment_iter_next(itor)) { alignment_entry_t *ent = alignment_iter_get(itor); double nsec = (double) ent->duration / frate; double endtime = starttime + nsec; size_t nsamp = (size_t) (nsec * samprate); E_INFO("Processing %d samples for %s (%f seconds ending %f)\n", nsamp, dict_wordstr(search_factory_d2p(bd->sf)->dict, ent->id.wid), nsec, endtime); E_INFO("Woke up at delta %f\n", get_time_delta(bd)); while (nsamp > 0) { size_t nread = 512; if (nread > nsamp) nread = nsamp; nread = fread(buf, sizeof(int16), nread, infh); if (nread == 0) break; featbuf_producer_process_raw(fb, buf, nread, FALSE); nsamp -= nread; starttime += (nread / samprate); double delta = get_time_delta(bd); if (starttime > delta) { E_INFO("Sleeping until next start time (%f seconds)\n", starttime - delta); usleep((int)((starttime - delta) * 1000000)); } } double delta = get_time_delta(bd); if (endtime > delta) { E_INFO("Sleeping until end time (%f seconds)\n", endtime - delta); usleep((int)((endtime - delta) * 1000000)); } } } else { while (ef == -1 || sf < ef) { size_t nread = 512; if (ef != -1 && nread > ef - sf) nread = ef - sf; nread = fread(buf, sizeof(int16), nread, infh); if (nread == 0) break; featbuf_producer_process_raw(fb, buf, nread, FALSE); //usleep((int)((double)nread / 16000 * 1000000)); sf += nread; } } return 0; }
/** * Return nanoseconds since start of copy. * * @returns nanoseconds since program start as a 64 bit unsigned integer. */ uint64_t get_time_delta(void) { static struct timeval stv = {.tv_sec = 0}; struct timeval ctv; if (gettimeofday(&ctv, NULL) < 0) fserr(PCOPY_EXIT_FAILURE, "gettimeofday", "current"); if (stv.tv_sec == 0) stv = ctv; if (stv.tv_sec == ctv.tv_sec) return (ctv.tv_usec - stv.tv_usec) * THOUSAND; uint64_t res = ctv.tv_sec - stv.tv_sec - 1; res *= MILLION; res += (MILLION - stv.tv_usec) + ctv.tv_usec; return res * THOUSAND; // micros to nanos } /** * Start up the copy of a segment. Once the open is complete and * the seek to the correct offset is done, let the main thread know * it can continue with the next thread. We start one at a time. * * @param[in,out] fseg The descriptor of the segment to copy. */ void copy_start(file_seg_t * fseg) { static char const st_fmt[] = "th %2d reading 0x%08lX"; if (! HAVE_OPT(QUIET)) { pthread_mutex_lock(&tty_mutex); if (fseg->idx == 0) { move(0,0); printw("copying %s", fseg->fname); move(1,0); printw("copy to %s", fseg->dname); } move(ENTRY_LINE, 0); printw(st_fmt, fseg->idx, fseg->start); refresh(); pthread_mutex_unlock(&tty_mutex); } fseg->fdin = open(fseg->fname, O_RDONLY); if (fseg->fdin < 0) fserr(PCOPY_EXIT_FS_ERR_IN, "open (r)", fseg->fname); fseg->fdout = open(fseg->dname, O_RDWR | O_CREAT, 0600); if (fseg->fdout < 0) fserr(PCOPY_EXIT_FS_ERR_OUT, "open (w)", fseg->dname); if (fseg->start > 0) { if (lseek(fseg->fdin, fseg->start, SEEK_SET) != fseg->start) fserr(PCOPY_EXIT_FS_ERR_IN, "seek (in)", fseg->fname); if (lseek(fseg->fdout, fseg->start, SEEK_SET) != fseg->start) fserr(PCOPY_EXIT_FS_ERR_OUT, "seek (out)", fseg->dname); } if (posix_fadvise(fseg->fdin, fseg->start, fseg->end - fseg->start, POSIX_FADV_SEQUENTIAL) != 0) fserr(PCOPY_EXIT_FS_ERR_IN, "fadvise(r)", fseg->fname); if (posix_fadvise(fseg->fdout, fseg->start, fseg->end - fseg->start, POSIX_FADV_SEQUENTIAL) != 0) fserr(PCOPY_EXIT_FS_ERR_OUT, "fadvise(w)", fseg->dname); pthread_mutex_lock(&th_start_mutex); pthread_cond_signal(&th_start_cond); pthread_mutex_unlock(&th_start_mutex); fseg->lastt = get_time_delta(); } /** * Show copy progress. The display happens if "quiet" has not been * specified. This function will also sleep, if "flow-rate" has * been specified and the time since the last segment read has been * too short. * * @param[in,out] fseg file segment descriptor. "lastt" may be updated. */ void copy_progress(file_seg_t * fseg) { static char const prg_fmt[] = " read to 0x%08lX togo 0x%08lX"; if (! HAVE_OPT(QUIET)) { pthread_mutex_lock(&tty_mutex); move(ENTRY_LINE + 1, 0); printw(prg_fmt, fseg->start, fseg->end - fseg->start); refresh(); pthread_mutex_unlock(&tty_mutex); } if (HAVE_OPT(FLOW_RATE)) { uint64_t cdelta = get_time_delta(); // delta from start uint64_t chunk_time = cdelta - fseg->lastt; // since chunk start /* * If the time used is more than 1/100 of a second less than * the time that is supposed to be consumed, then nanosleep. */ if (chunk_time < nsec_per_iteration - (10*MILLION)) { uint64_t slptm = nsec_per_iteration - chunk_time; struct timespec ts = { .tv_sec = (slptm > BILLION) ? (slptm / BILLION) : 0, .tv_nsec = (slptm > BILLION) ? (slptm % BILLION) : slptm }; (void)nanosleep(&ts, NULL); fseg->lastt = get_time_delta(); } else { fseg->lastt = cdelta; } } }