int main(int argc, char** argv ) { printf("%25s\t%15s\t%15s\t%15s\n", "clock", "res (ns)", "secs", "nsecs"); struct timeval tv; gettimeofday(&tv, NULL); printf("%25s\t%15s\t%15s\t", "gettimeofday","1,000", commaprint(tv.tv_sec)); printf("%15s\n", commaprint(tv.tv_usec*1000)); #if _POSIX_TIMERS > 0 #ifdef CLOCK_REALTIME do_clock(CLOCK_REALTIME); #endif #ifdef CLOCK_REALTIME_COARSE do_clock(CLOCK_REALTIME_COARSE); #endif #ifdef CLOCK_REALTIME_HR do_clock(CLOCK_REALTIME_HR); #endif #ifdef CLOCK_MONOTONIC do_clock(CLOCK_MONOTONIC); #endif #ifdef CLOCK_MONOTONIC_RAW do_clock(CLOCK_MONOTONIC_RAW); #endif #ifdef CLOCK_MONOTONIC_COARSE do_clock(CLOCK_MONOTONIC_COARSE); #endif #endif return 0; }
static void render_update_stats(SlidingWindow *priv) { werase(priv->access_time_stats); unsigned int i; for (i = 0; i < 6; i++) wprintw(priv->access_time_stats, "%d\n", priv->access_time_stats_accum[i]); for (i = 1; i < 7; i++) wprintw(priv->access_time_stats, "%d\n", priv->error_stats_accum[i]); wnoutrefresh(priv->access_time_stats); if (priv->avg_processing_speed != 0) { werase(priv->avg_speed); wprintw(priv->avg_speed, "SPEED %7"PRIu64" kb/s", priv->avg_processing_speed / 1024); wnoutrefresh(priv->avg_speed); } if (priv->eta_time != 0) { unsigned int minute, second; second = priv->eta_time % 60; minute = priv->eta_time / 60; werase(priv->eta); wprintw(priv->eta, "ETA %11u:%02u", minute, second); wnoutrefresh(priv->eta); } werase(priv->w_cur_lba); char comma_lba_buf[30], *comma_lba_p; comma_lba_p = commaprint(priv->cur_lba, comma_lba_buf, sizeof(comma_lba_buf)); wprintw(priv->w_cur_lba, "LBA: %14s", comma_lba_p); wnoutrefresh(priv->w_cur_lba); }
static void render_update_stats(WholeSpace *priv) { if (priv->avg_processing_speed != 0) { werase(priv->avg_speed); wprintw(priv->avg_speed, "SPEED %7"PRIu64" kb/s", priv->avg_processing_speed / 1024); wnoutrefresh(priv->avg_speed); } if (priv->eta_time != 0) { unsigned int minute, second; second = priv->eta_time % 60; minute = priv->eta_time / 60; werase(priv->eta); wprintw(priv->eta, "ETA %11u:%02u", minute, second); wnoutrefresh(priv->eta); } werase(priv->w_cur_lba); char comma_lba_buf[30], *comma_lba_p; comma_lba_p = commaprint(priv->cur_lba, comma_lba_buf, sizeof(comma_lba_buf)); wprintw(priv->w_cur_lba, "LBA: %14s", comma_lba_p); wnoutrefresh(priv->w_cur_lba); werase(priv->w_stats); print_vis(priv->w_stats, bs_vis[0]); wattrset(priv->w_stats, A_NORMAL); wprintw(priv->w_stats, " %"PRIu64"\n", priv->unread_count); print_vis(priv->w_stats, bs_vis[3]); wattrset(priv->w_stats, A_NORMAL); wprintw(priv->w_stats, " %"PRIu64"\n", priv->read_ok_count); print_vis(priv->w_stats, error_vis[3]); wattrset(priv->w_stats, A_NORMAL); wprintw(priv->w_stats, " %"PRIu64"\n", priv->errors_count); wnoutrefresh(priv->w_stats); }
/* 25x80 <--LEGEND_WIDTH=20-> +--------------------------------------------------------------------------------+ | LBA: xxx,xxx / xxx,xxx,xxx ETA xx:xx | |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx SPEED xxxxx kb/s | |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x <3ms xxxx |^ |xxxxxxxxxxxxxxxxxxxxxxxxx x <10ms xxx || | x <50ms xx || | x <150ms x || | x <500ms x || | x >500ms x || LEGEND_HEIGHT=12 | x ERR x || | ? TIME x || | x UNC x || | S IDNF x || | ! ABRT x || | A AMNF x |v | | | Read test /dev/XXX | | Block = 131072 bytes| | | | Ctrl+C to abort | | | | | | | | | | WHDD rev. X.X-X-gXXXXXXX | +--------------------------------------------------------------------------------+ */ static int Open(DC_RendererCtx *ctx) { SlidingWindow *priv = ctx->priv; DC_ProcedureCtx *actctx = ctx->procedure_ctx; // TODO Raise error message if (LINES < 25 || COLS < 80) return -1; #define LBA_WIDTH 20 #define LEGEND_WIDTH 20 #define LEGEND_HEIGHT 12 #define LEGEND_VERT_OFFSET 3 /* ETA & SPEED are above, 1 for spacing */ priv->w_cur_lba = derwin(stdscr, 1, LBA_WIDTH, 0 /* at the top */, COLS - LEGEND_WIDTH - 1 - (LBA_WIDTH * 2) ); assert(priv->w_cur_lba); wbkgd(priv->w_cur_lba, COLOR_PAIR(MY_COLOR_GRAY)); priv->w_end_lba = derwin(stdscr, 1, LBA_WIDTH, 0 /* at the top */, COLS - LEGEND_WIDTH - 1 - LBA_WIDTH); assert(priv->w_end_lba); wbkgd(priv->w_end_lba, COLOR_PAIR(MY_COLOR_GRAY)); priv->eta = derwin(stdscr, 1, LEGEND_WIDTH, 0 /* at the top */, COLS-LEGEND_WIDTH); assert(priv->eta); wbkgd(priv->eta, COLOR_PAIR(MY_COLOR_GRAY)); priv->avg_speed = derwin(stdscr, 1, LEGEND_WIDTH, 1 /* ETA is above */, COLS-LEGEND_WIDTH); assert(priv->avg_speed); wbkgd(priv->avg_speed, COLOR_PAIR(MY_COLOR_GRAY)); priv->legend = derwin(stdscr, LEGEND_HEIGHT, LEGEND_WIDTH/2, LEGEND_VERT_OFFSET, COLS-LEGEND_WIDTH); assert(priv->legend); wbkgd(priv->legend, COLOR_PAIR(MY_COLOR_GRAY)); priv->access_time_stats = derwin(stdscr, LEGEND_HEIGHT, LEGEND_WIDTH/2, LEGEND_VERT_OFFSET, COLS-LEGEND_WIDTH/2); assert(priv->access_time_stats); wbkgd(priv->access_time_stats, COLOR_PAIR(MY_COLOR_GRAY)); show_legend(priv->legend); #define SUMMARY_VERT_OFFSET ( 1 /* ETA */ + 1 + /* SPEED */ + 1 /* spacing */ + LEGEND_HEIGHT + 1 /* spacing */ ) #define SUMMARY_HEIGHT ( LINES - SUMMARY_VERT_OFFSET - 1 /* don't touch bottom line */ ) priv->summary = derwin(stdscr, SUMMARY_HEIGHT, LEGEND_WIDTH, SUMMARY_VERT_OFFSET, COLS-LEGEND_WIDTH); assert(priv->summary); wbkgd(priv->summary, COLOR_PAIR(MY_COLOR_GRAY)); priv->vis = derwin(stdscr, LINES-2 /* version is below, LBA is above */, COLS-LEGEND_WIDTH-1, 1 /* LBA is above */, 0); assert(priv->vis); scrollok(priv->vis, TRUE); wrefresh(priv->vis); priv->reports[0].seqno = 1; // anything but zero char comma_lba_buf[30], *comma_lba_p; comma_lba_p = commaprint(actctx->dev->capacity / 512, comma_lba_buf, sizeof(comma_lba_buf)); wprintw(priv->w_end_lba, "/ %s", comma_lba_p); wnoutrefresh(priv->w_end_lba); wprintw(priv->summary, "%s %s\n" "Block = %d bytes\n" "Ctrl+C to abort\n", actctx->procedure->display_name, actctx->dev->dev_path, actctx->blk_size); wrefresh(priv->summary); int r = pthread_create(&priv->render_thread, NULL, render_thread_proc, priv); if (r) return r; // FIXME leak return 0; }
/* Function: main() * Synopsis: Run set of queries against an FM * Purpose: Read in a FM and a file of query sequences. * For each query, find matching FM interval, then collect positions in * the original text T for the corresponding occurrences. These positions * are 0-based (so first character is position 0). */ int main(int argc, char *argv[]) { void* tmp; // used for RALLOC calls clock_t t1, t2; struct tms ts1, ts2; char *fname_fm = NULL; char *fname_queries = NULL; FM_HIT *hits = NULL; char *line = NULL; int status = eslOK; int hit_cnt = 0; int hit_indiv_cnt = 0; int miss_cnt = 0; int hit_num = 0; int hit_num2 = 0; int hits_size = 0; int i,j; int count_only = 0; FM_INTERVAL interval; FM_DATA *fmsf = NULL; FM_DATA *fmsb = NULL; FILE* fp_fm = NULL; FILE* fp = NULL; FILE* out = NULL; char *outname = NULL; ESL_GETOPTS *go = NULL; /* command line processing */ FM_CFG *cfg; FM_METADATA *meta; ESL_SQ *tmpseq; // used for sequence validation ESL_ALPHABET *abc = NULL; //start timer t1 = times(&ts1); process_commandline(argc, argv, &go, &fname_fm, &fname_queries); if (esl_opt_IsOn(go, "--out")) { outname = esl_opt_GetString(go, "--out"); if ( esl_strcmp ("-", outname) == 0 ) { out = stdout; outname = "stdout"; } else { out = fopen(outname,"w"); } } if (esl_opt_IsOn(go, "--count_only")) count_only = 1; if((fp_fm = fopen(fname_fm, "rb")) == NULL) esl_fatal("Cannot open file `%s': ", fname_fm); fm_configAlloc(&cfg); cfg->occCallCnt = 0; meta = cfg->meta; meta->fp = fp_fm; fm_readFMmeta( meta); if (meta->alph_type == fm_DNA) abc = esl_alphabet_Create(eslDNA); else if (meta->alph_type == fm_AMINO) abc = esl_alphabet_Create(eslAMINO); tmpseq = esl_sq_CreateDigital(abc); //read in FM-index blocks ESL_ALLOC(fmsf, meta->block_count * sizeof(FM_DATA) ); if (!meta->fwd_only) ESL_ALLOC(fmsb, meta->block_count * sizeof(FM_DATA) ); for (i=0; i<meta->block_count; i++) { fm_FM_read( fmsf+i,meta, TRUE ); if (!meta->fwd_only) { fm_FM_read(fmsb+i, meta, FALSE ); fmsb[i].SA = fmsf[i].SA; fmsb[i].T = fmsf[i].T; } } fclose(fp_fm); output_header(meta, stdout, go, fname_fm, fname_queries); /* initialize a few global variables, then call initGlobals * to do architecture-specific initialization */ fm_configInit(cfg, NULL); fm_alphabetCreate(meta, NULL); // don't override charBits fp = fopen(fname_queries,"r"); if (fp == NULL) esl_fatal("Unable to open file %s\n", fname_queries); ESL_ALLOC(line, FM_MAX_LINE * sizeof(char)); hits_size = 200; ESL_ALLOC(hits, hits_size * sizeof(FM_HIT)); while(fgets(line, FM_MAX_LINE, fp) ) { int qlen=0; while (line[qlen] != '\0' && line[qlen] != '\n') qlen++; if (line[qlen] == '\n') line[qlen] = '\0'; hit_num = 0; for (i=0; i<meta->block_count; i++) { fm_getSARangeReverse(fmsf+i, cfg, line, meta->inv_alph, &interval); if (interval.lower>=0 && interval.lower <= interval.upper) { int new_hit_num = interval.upper - interval.lower + 1; hit_num += new_hit_num; if (!count_only) { if (hit_num > hits_size) { hits_size = 2*hit_num; ESL_RALLOC(hits, tmp, hits_size * sizeof(FM_HIT)); } getFMHits(fmsf+i, cfg, &interval, i, hit_num-new_hit_num, qlen, hits, fm_forward); } } /* find reverse hits, using backward search on the forward FM*/ if (!meta->fwd_only) { fm_getSARangeForward(fmsb+i, cfg, line, meta->inv_alph, &interval);// yes, use the backward fm to produce the equivalent of a forward search on the forward fm if (interval.lower>=0 && interval.lower <= interval.upper) { int new_hit_num = interval.upper - interval.lower + 1; hit_num += new_hit_num; if (!count_only) { if (hit_num > hits_size) { hits_size = 2*hit_num; ESL_RALLOC(hits, tmp, hits_size * sizeof(FM_HIT)); } //even though I used fmsb above, use fmsf here, since we'll now do a backward trace //in the FM-index to find the next sampled SA position getFMHits(fmsf+i, cfg, &interval, i, hit_num-new_hit_num, qlen, hits, fm_backward); } } } } if (hit_num > 0) { if (count_only) { hit_cnt++; hit_indiv_cnt += hit_num; } else { hit_num2 = 0; //for each hit, identify the sequence id and position within that sequence for (i = 0; i< hit_num; i++) { status = fm_getOriginalPosition (fmsf, meta, hits[i].block, hits[i].length, fm_forward, hits[i].start, &(hits[i].block), &(hits[i].start) ); hits[i].sortkey = (status==eslERANGE ? -1 : meta->seq_data[ hits[i].block ].target_id); //validate match - if any characters in orig sequence were ambiguities, reject fm_convertRange2DSQ( fmsf, meta, hits[i].start, hits[i].length, p7_NOCOMPLEMENT, tmpseq, TRUE ); for (j=1; j<=hits[i].length; j++) { if (tmpseq->dsq[j] >= abc->K) { hits[i].sortkey = -1; //reject j = hits[i].length+1; //quit looking } } if (hits[i].sortkey != -1) hit_num2++; // legitimate hit } if (hit_num2 > 0) hit_cnt++; //now sort according the the sequence_id corresponding to that seq_offset qsort(hits, hit_num, sizeof(FM_HIT), hit_sorter); //skim past the skipped entries i = 0; while ( i < hit_num ) { if (hits[i].sortkey != -1 ) break; // i++; } if (i < hit_num) { if (out != NULL) { fprintf (out, "%s\n",line); //fprintf (out, "\t%10s (%8d %s)\n",meta->seq_data[ hits[i].block ].name, hits[i].start, (hits[i].direction==fm_forward?"+":"-")); fprintf (out, " %8ld %s %10s\n", (long)(hits[i].start), (hits[i].direction==fm_forward?"f":"r"), meta->seq_data[ hits[i].block ].name); } hit_indiv_cnt++; i++; // skip the first one, since I'll be comparing each to the previous for ( ; i< hit_num; i++) { if ( //meta->seq_data[ hits[i].block ].id != meta->seq_data[ hits[i-1].block ].id || hits[i].sortkey != hits[i-1].sortkey || //sortkey is seq_data[].id hits[i].direction != hits[i-1].direction || hits[i].start != hits[i-1].start ) { if (out != NULL) //fprintf (out, "\t%10s (%8d %s)\n",meta->seq_data[ hits[i].block ].name, hits[i].start, (hits[i].direction==fm_forward?"+":"-")); fprintf (out, " %8ld %s %10s\n", (long)(hits[i].start), (hits[i].direction==fm_forward?"f":"r"), meta->seq_data[ hits[i].block ].name); hit_indiv_cnt++; } } if (out != NULL) fprintf (out, "\n"); } } } else { miss_cnt++; } } for (i=0; i<meta->block_count; i++) { fm_FM_destroy( fmsf+i, 1 ); if (!meta->fwd_only) fm_FM_destroy( fmsb+i, 0 ); } free (hits); free (line); fclose(fp); fm_configDestroy(cfg); // compute and print the elapsed time in millisec t2 = times(&ts2); { double clk_ticks = sysconf(_SC_CLK_TCK); double elapsedTime = (t2-t1)/clk_ticks; double throughput = cfg->occCallCnt/elapsedTime; fprintf (stderr, "hit: %-10d (%d)\n", hit_cnt, hit_indiv_cnt); fprintf (stderr, "miss:%-10d\n", miss_cnt); fprintf (stderr, "run time: %.2f seconds\n", elapsedTime); fprintf (stderr, "occ calls: %12s\n", commaprint(cfg->occCallCnt)); fprintf (stderr, "occ/sec: %12s\n", commaprint(throughput)); } exit(eslOK); ERROR: printf ("failure allocating memory for hits\n"); exit(status); }
static int Open(DC_RendererCtx *ctx) { WholeSpace *priv = ctx->priv; DC_ProcedureCtx *actctx = ctx->procedure_ctx; priv->nb_blocks = actctx->dev->capacity / actctx->blk_size; if (actctx->dev->capacity % actctx->blk_size) priv->nb_blocks++; priv->unread_count = actctx->progress.den; priv->sectors_per_block = actctx->blk_size / 512; priv->blocks_map = calloc(priv->nb_blocks, sizeof(uint8_t)); assert(priv->blocks_map); int journal_fd = ((CopyPriv*)actctx->priv)->journal_fd; lseek(journal_fd, 0, SEEK_SET); if (((CopyPriv*)actctx->priv)->use_journal) { priv->unread_count = 0; uint8_t journal_chunk[1*1024*1024]; int64_t chunklen; int64_t end_lba = ((CopyPriv*)actctx->priv)->end_lba; for (int64_t i = 0; i < priv->nb_blocks; i++) { int64_t lba = i * priv->sectors_per_block; if (lba % sizeof(journal_chunk) == 0) { chunklen = (end_lba - lba) < (int64_t)sizeof(journal_chunk) ? (end_lba - lba) : (int64_t)sizeof(journal_chunk); int ret = read(journal_fd, journal_chunk, chunklen); if (ret != chunklen) return 1; } char sector_status = journal_chunk[lba % sizeof(journal_chunk)]; priv->blocks_map[i] = sector_status; int sectors_in_block = priv->sectors_per_block; if (i == priv->nb_blocks - 1) // Last block may be smaller sectors_in_block = (actctx->dev->capacity % actctx->blk_size) / 512; switch ((enum SectorStatus)sector_status) { case SectorStatus_eUnread: priv->unread_count += sectors_in_block; break; case SectorStatus_eReadOk: priv->read_ok_count += sectors_in_block; break; case SectorStatus_eBlockReadError: case SectorStatus_eSectorReadError: priv->errors_count += sectors_in_block; break; } } } priv->legend = derwin(stdscr, 9 /* legend win height */, LEGEND_WIDTH, 4, COLS-LEGEND_WIDTH); // leave 1st and last lines untouched assert(priv->legend); wbkgd(priv->legend, COLOR_PAIR(MY_COLOR_GRAY)); priv->w_stats = derwin(stdscr, 3, LEGEND_WIDTH, 4+9, COLS-LEGEND_WIDTH); assert(priv->w_stats); priv->vis_height = LINES - 5; priv->vis_width = COLS - LEGEND_WIDTH - 1; int vis_cells_avail = priv->vis_height * priv->vis_width; priv->blocks_per_vis = priv->nb_blocks / vis_cells_avail; if (priv->nb_blocks % vis_cells_avail) priv->blocks_per_vis++; priv->vis = derwin(stdscr, priv->vis_height, priv->vis_width, 2, 0); // leave 1st and last lines untouched assert(priv->vis); wrefresh(priv->vis); whole_space_show_legend(priv); priv->avg_speed = derwin(stdscr, 1, LEGEND_WIDTH, 2, COLS-LEGEND_WIDTH); assert(priv->avg_speed); wbkgd(priv->avg_speed, COLOR_PAIR(MY_COLOR_GRAY)); priv->eta = derwin(stdscr, 1, LEGEND_WIDTH, 1, COLS-LEGEND_WIDTH); assert(priv->eta); wbkgd(priv->eta, COLOR_PAIR(MY_COLOR_GRAY)); priv->summary = derwin(stdscr, 10, LEGEND_WIDTH, 16, COLS-LEGEND_WIDTH); assert(priv->summary); wbkgd(priv->summary, COLOR_PAIR(MY_COLOR_GRAY)); priv->w_end_lba = derwin(stdscr, 1, 20, 1, COLS-41); assert(priv->w_end_lba); wbkgd(priv->w_end_lba, COLOR_PAIR(MY_COLOR_GRAY)); priv->w_cur_lba = derwin(stdscr, 1, 20, 1, COLS-61); assert(priv->w_cur_lba); wbkgd(priv->w_cur_lba, COLOR_PAIR(MY_COLOR_GRAY)); priv->w_log = derwin(stdscr, 2, COLS, LINES-3, 0); assert(priv->w_log); scrollok(priv->w_log, TRUE); wbkgd(priv->w_log, COLOR_PAIR(MY_COLOR_GRAY)); priv->reports[0].seqno = 1; // anything but zero char comma_lba_buf[30], *comma_lba_p; comma_lba_p = commaprint(actctx->dev->capacity / 512, comma_lba_buf, sizeof(comma_lba_buf)); wprintw(priv->w_end_lba, "/ %s", comma_lba_p); wnoutrefresh(priv->w_end_lba); wprintw(priv->summary, "%s %s\n" "Ctrl+C to abort\n", actctx->procedure->display_name, actctx->dev->dev_path); wrefresh(priv->summary); int r = pthread_create(&priv->render_thread, NULL, render_thread_proc, priv); if (r) return r; // FIXME leak return 0; }
/* 25x80 <--LEGEND_WIDTH=20-> +--------------------------------------------------------------------------------+ | LBA: xxx,xxx / xxx,xxx,xxx ETA xx:xx | |ZZZZZZZZZZZZZZZxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx SPEED xxxxx kb/s | |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x unread space |^ |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x copied space, || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx no read errors || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x read errors || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx occured || LEGEND_HEIGHT=9 |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Display block is XXX|| |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx XXX blocks by 256 se|| |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ctors |v |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x NNNNNNNNNN |^ |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x NNNNNNNNNN || W_STATS_HEIGHT=3 |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x NNNNNNNNNN |v |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Device copying /dev/|^ |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx XXX || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Ctrl+C to abort || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || SUMMARY |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx || |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |v | WHDD rev. X.X-X-gXXXXXXX | +--------------------------------------------------------------------------------+ */ static int Open(DC_RendererCtx *ctx) { WholeSpace *priv = ctx->priv; DC_ProcedureCtx *actctx = ctx->procedure_ctx; // TODO Raise error message if (LINES < 25 || COLS < 80) return -1; priv->nb_blocks = actctx->dev->capacity / actctx->blk_size; if (actctx->dev->capacity % actctx->blk_size) priv->nb_blocks++; priv->unread_count = actctx->progress.den; priv->sectors_per_block = actctx->blk_size / 512; priv->blocks_map = calloc(priv->nb_blocks, sizeof(uint8_t)); assert(priv->blocks_map); int journal_fd = ((CopyPriv*)actctx->priv)->journal_fd; lseek(journal_fd, 0, SEEK_SET); if (((CopyPriv*)actctx->priv)->use_journal) { priv->unread_count = 0; uint8_t journal_chunk[1*1024*1024]; int64_t chunklen; int64_t end_lba = ((CopyPriv*)actctx->priv)->end_lba; for (int64_t i = 0; i < priv->nb_blocks; i++) { int64_t lba = i * priv->sectors_per_block; if (lba % sizeof(journal_chunk) == 0) { chunklen = (end_lba - lba) < (int64_t)sizeof(journal_chunk) ? (end_lba - lba) : (int64_t)sizeof(journal_chunk); int ret = read(journal_fd, journal_chunk, chunklen); if (ret != chunklen) return 1; } char sector_status = journal_chunk[lba % sizeof(journal_chunk)]; priv->blocks_map[i] = sector_status; int sectors_in_block = priv->sectors_per_block; if (i == priv->nb_blocks - 1) // Last block may be smaller sectors_in_block = (actctx->dev->capacity % actctx->blk_size) / 512; switch ((enum SectorStatus)sector_status) { case SectorStatus_eUnread: priv->unread_count += sectors_in_block; break; case SectorStatus_eReadOk: priv->read_ok_count += sectors_in_block; break; case SectorStatus_eBlockReadError: case SectorStatus_eSectorReadError: priv->errors_count += sectors_in_block; break; } } } #define LBA_WIDTH 20 #define LEGEND_WIDTH 20 #define LEGEND_HEIGHT 9 #define LEGEND_VERT_OFFSET 3 /* ETA & SPEED are above, 1 for spacing */ priv->w_cur_lba = derwin(stdscr, 1, LBA_WIDTH, 0 /* at the top */, COLS - LEGEND_WIDTH - 1 - (LBA_WIDTH * 2) ); assert(priv->w_cur_lba); wbkgd(priv->w_cur_lba, COLOR_PAIR(MY_COLOR_GRAY)); priv->w_end_lba = derwin(stdscr, 1, LBA_WIDTH, 0 /* at the top */, COLS - LEGEND_WIDTH - 1 - LBA_WIDTH); assert(priv->w_end_lba); wbkgd(priv->w_end_lba, COLOR_PAIR(MY_COLOR_GRAY)); priv->eta = derwin(stdscr, 1, LEGEND_WIDTH, 0 /* at the top */, COLS-LEGEND_WIDTH); assert(priv->eta); wbkgd(priv->eta, COLOR_PAIR(MY_COLOR_GRAY)); priv->avg_speed = derwin(stdscr, 1, LEGEND_WIDTH, 1 /* ETA is above */, COLS-LEGEND_WIDTH); assert(priv->avg_speed); wbkgd(priv->avg_speed, COLOR_PAIR(MY_COLOR_GRAY)); priv->legend = derwin(stdscr, LEGEND_HEIGHT, LEGEND_WIDTH, LEGEND_VERT_OFFSET, COLS-LEGEND_WIDTH); assert(priv->legend); wbkgd(priv->legend, COLOR_PAIR(MY_COLOR_GRAY)); #define W_STATS_HEIGHT 3 #define W_STATS_VERT_OFFSET ( LEGEND_VERT_OFFSET + LEGEND_HEIGHT + 1 /* spacing */ ) priv->w_stats = derwin(stdscr, W_STATS_HEIGHT, LEGEND_WIDTH, W_STATS_VERT_OFFSET, COLS-LEGEND_WIDTH); assert(priv->w_stats); #define SUMMARY_VERT_OFFSET ( W_STATS_VERT_OFFSET + W_STATS_HEIGHT + 1 /* spacing */ ) #define SUMMARY_HEIGHT ( LINES - SUMMARY_VERT_OFFSET - 1 /* don't touch bottom line */ ) priv->summary = derwin(stdscr, SUMMARY_HEIGHT, LEGEND_WIDTH, SUMMARY_VERT_OFFSET, COLS-LEGEND_WIDTH); assert(priv->summary); wbkgd(priv->summary, COLOR_PAIR(MY_COLOR_GRAY)); priv->vis_height = LINES - 2; /* LBA is above, version is below */ priv->vis_width = COLS - LEGEND_WIDTH - 1; int vis_cells_avail = priv->vis_height * priv->vis_width; priv->blocks_per_vis = priv->nb_blocks / vis_cells_avail; if (priv->nb_blocks % vis_cells_avail) priv->blocks_per_vis++; priv->vis = derwin(stdscr, priv->vis_height, priv->vis_width, 1 /* LBA is above */, 0); assert(priv->vis); wrefresh(priv->vis); whole_space_show_legend(priv); priv->reports[0].seqno = 1; // anything but zero char comma_lba_buf[30], *comma_lba_p; comma_lba_p = commaprint(actctx->dev->capacity / 512, comma_lba_buf, sizeof(comma_lba_buf)); wprintw(priv->w_end_lba, "/ %s", comma_lba_p); wnoutrefresh(priv->w_end_lba); wprintw(priv->summary, "%s %s\n" "Ctrl+C to abort\n", actctx->procedure->display_name, actctx->dev->dev_path); wrefresh(priv->summary); int r = pthread_create(&priv->render_thread, NULL, render_thread_proc, priv); if (r) return r; // FIXME leak return 0; }