void exception_print (struct ui_file *file, struct gdb_exception e) { if (e.reason < 0 && e.message != NULL) { print_flush (); print_exception (file, e); } }
static bool rewind_tape(int fd) { static struct mtop rewind = { MTREW, 1 }; print_flush("Rewinding tape... "); int failed = ioctl(fd, MTIOCTOP, &rewind); if (failed != 0) printf("Rewind failed => %m\n"); else printf(", done\n"); return failed == 0; }
void exception_fprintf (struct ui_file *file, struct gdb_exception e, const char *prefix, ...) { if (e.reason < 0 && e.message != NULL) { va_list args; print_flush (); /* Print the prefix. */ va_start (args, prefix); vfprintf_filtered (file, prefix, args); va_end (args); print_exception (file, e); } }
/* Checks for a flush given arrays for the pips and suit values from a load of * cards. The check is terminated when the first flush is found. */ void check_flush(int n, pips p[], suit s[]) { int i, j, k, cnt[4][13]; pips flush[5]; //Used to store pips values of cards in a potential flush. //Initialise all elements of cnt[][] to zero: for (i = 0; i < 4; ++i) { for (j = 0; j < 13; ++j) { cnt[i][j] = 0; } } //Record the cards in cnt[][] using s[] and p[]. for (i = 0; i < n; ++i) { cnt[s[i] - 1][p[i] - 1]++; } //Loop over the set of suits: for (i = 0, k = 4; i < 4 && k > 0; ++i) { //Reset flush elements to zero. for (; k >= 0; --k) { flush[k] = 0; } /* For the current suit, add the first five pips values present * in cnt[] to flush[] in descending order. */ for (j = 13, k = 5; j > 0 && k > 0; --j) { if (cnt[i][j % 13] && k > 0) { /* Add the pips value to the potential flush if not already * complete: */ flush[--k] = (pips) ((j % 13) + 1); } } //If the flush is complete, terminate the loop and display the flush: if (k == 0) { print_flush(flush, i + 1); break; } } }
int main(int argc, char ** argv) { static char * buffer[32]; static char buffer_size[16]; const char * device = DEFAULT_DEVICE; ssize_t size = DEFAULT_SIZE; bool no_rewind = false; bool rewind = false; ssize_t max_buffer_size = MAX_BUFFER_SIZE; ssize_t min_buffer_size = MIN_BUFFER_SIZE; ssize_t tmp_size = 0; enum { OPT_DEVICE = 'd', OPT_HELP = 'h', OPT_MAX_BUFFER = 'M', OPT_MIN_BUFFER = 'm', OPT_NO_REWIND = 'r', OPT_REWIND = 'R', OPT_SIZE = 's', OPT_VERSION = 'V', }; static struct option op[] = { { "device", 1, 0, OPT_DEVICE }, { "help", 0, 0, OPT_HELP }, { "max-buffer-size", 1, 0, OPT_MAX_BUFFER }, { "min-buffer-size", 1, 0, OPT_MIN_BUFFER }, { "no-rewind", 0, 0, OPT_NO_REWIND }, { "size", 1, 0, OPT_SIZE }, { "rewind-at-start", 0, 0, OPT_REWIND }, { "version", 0, 0, OPT_VERSION }, { 0, 0, 0, 0 }, }; static int lo; for (;;) { int c = getopt_long(argc, argv, "d:hm:M:s:rRV?", op, &lo); if (c == -1) break; switch (c) { case OPT_DEVICE: device = optarg; break; case OPT_HELP: case '?': printf("tape-benchmark (" TAPEBENCHMARK_VERSION ")\n"); printf(" -d, --device=DEV : use this device DEV instead of \"" DEFAULT_DEVICE "\"\n"); printf(" -h, --help : show this and quit\n"); convert_size(buffer_size, 16, MAX_BUFFER_SIZE); printf(" -M, --max-buffer-size=SIZE : maximum buffer size (instead of %s)\n", buffer_size); convert_size(buffer_size, 16, MIN_BUFFER_SIZE); printf(" -m, --min-buffer-size=SIZE : minimum buffer size (instead of %s)\n", buffer_size); convert_size(buffer_size, 16, DEFAULT_SIZE); printf(" -s, --size=SIZE : size of file (default: %s)\n", buffer_size); printf(" -r, --no-rewind : no rewind tape between step (default: rewind between step)\n"); printf(" -R, --rewind-at-start : rewind tape before writing on tape, (default: no rewind at start)\n\n"); printf("SIZE can be specified with (BKGT)\n"); printf(" 1B => 1 byte, 1K => 1024B, 1M => 1024K, 1G => 1024M, 1T => 1024G\n"); printf("Another way to set the size is by specifying an integer which will be interpreted as a power of two.\n"); printf(" 10 => 2^10 bytes (= 1K), 16 => 2^16 bytes (= 64K), 24 => 2^24 bytes (= 16M), and so on\n"); printf("Constraint: min-buffer-size and max-buffer-size should be a power of two\n\n"); printf("Note: this programme will allocate 32 buffers of max-buffer-size\n"); return 0; case OPT_MAX_BUFFER: tmp_size = parse_size(optarg); if (check_size(tmp_size)) { max_buffer_size = tmp_size; } else { printf("Error: max-buffer-size should be a power of two\n"); return 1; } break; case OPT_MIN_BUFFER: tmp_size = parse_size(optarg); if (check_size(tmp_size)) { min_buffer_size = tmp_size; } else { printf("Error: min-buffer-size should be a power of two\n"); return 1; } break; case OPT_NO_REWIND: no_rewind = true; break; case OPT_SIZE: size = parse_size(optarg); break; case OPT_REWIND: rewind = true; break; case OPT_VERSION: printf("tape-benchmark (" TAPEBENCHMARK_VERSION ", date and time : " __DATE__ " " __TIME__ ")\n"); printf("checksum of source code: " TAPEBENCHMARK_SRCSUM "\n"); printf("git commit: " TAPEBENCHMARK_GIT_COMMIT "\n"); return 0; } } print_time(); print_flush("Openning \"%s\"... ", device); int fd_tape = open(device, O_RDONLY); if (fd_tape < 0) { printf("failed!!!, because %m\n"); return 2; } struct mtget mt; int failed = ioctl(fd_tape, MTIOCGET, &mt); if (failed != 0) { close(fd_tape); printf("Oops: seem not to be a valid tape device\n"); return 2; } if (GMT_WR_PROT(mt.mt_gstat)) { close(fd_tape); printf("Oops: Write lock enabled\n"); return 2; } failed = close(fd_tape); fd_tape = open(device, O_WRONLY); if (fd_tape < 0) { printf("failed!!!, because %m\n"); return 2; } else { printf("fd: %d\n", fd_tape); } if (rewind && !rewind_tape(fd_tape)) return 2; ssize_t current_block_size = (mt.mt_dsreg & MT_ST_BLKSIZE_MASK) >> MT_ST_BLKSIZE_SHIFT; print_time(); print_flush("Generate random data from \"/dev/urandom\"... "); int fd_ran = open("/dev/urandom", O_RDONLY); if (fd_ran < 0) { printf("Failed to open because %m\n"); close(fd_tape); return 2; } int j; for (j = 0; j < 32; j++) { buffer[j] = malloc(max_buffer_size); if (buffer[j] == NULL) { printf("Error: failed to allocated memory (size: %zd) because %m\n", max_buffer_size); close(fd_tape); close(fd_ran); return 3; } ssize_t nb_read = read(fd_ran, buffer[j], max_buffer_size); if (nb_read < 0) printf("\nWarning: failed to read from \"/dev/urandom\" because %m\n"); else if (nb_read < max_buffer_size) printf("\nWarning: read less than expected, %zd instead of %zd\n", nb_read, max_buffer_size); } close(fd_ran); printf("done\n"); static char clean_line[64]; memset(clean_line, ' ', 64); ssize_t write_size; for (write_size = min_buffer_size; write_size <= max_buffer_size; write_size <<= 1) { if (current_block_size > 0) { write_size = current_block_size; printf("Warning: block size is defined to %zd instead of %zd\n", current_block_size, write_size); } struct pollfd plfd = { fd_tape, POLLOUT, 0 }; int pll_rslt = poll(&plfd, 1, 100); int poll_retry = 0; while (pll_rslt < 1) { if (poll_retry == 0) printf("Device is no ready, so we wait until"); else printf("."); fflush(stdout); poll_retry++; pll_rslt = poll(&plfd, 1, 6000); if (pll_rslt > 0) printf("\n"); } struct timeval time_start; gettimeofday(&time_start, NULL); ssize_t nb_loop = size / write_size; convert_size(buffer_size, 16, write_size); print_time(); printf("Starting, nb loop: %zd, block size: %s\n", nb_loop, buffer_size); struct timespec start, last, current; clock_gettime(CLOCK_MONOTONIC, &start); last = start; int write_error = 0; long long int i; static int last_width = 64; for (i = 0; i < nb_loop; i++) { ssize_t nb_write = write(fd_tape, buffer[i & 0x1F], write_size); if (nb_write < 0) { if (last_width > 0) printf("\r%*s\r", last_width, clean_line); switch (errno) { case EINVAL: convert_size(buffer_size, 16, write_size >> 1); printf("It seems that you cannot use a block size greater than %s\n", buffer_size); break; case EBUSY: printf("rDevice is busy, so we wait a few seconds before restarting\n"); sleep(8); print_time(); printf("Restarting, nb loop: %zd, block size: %s\n", nb_loop, buffer_size); i = -1; clock_gettime(CLOCK_MONOTONIC, &start); break; default: printf("Oops: an error occured => (%d) %m\n", errno); printf("fd: %d, buffer: %p, count: %zd\n", fd_tape, buffer[i & 0x1F], write_size); break; } write_error = 1; break; } clock_gettime(CLOCK_MONOTONIC, ¤t); if (last.tv_sec + 5 <= current.tv_sec) { float pct = 100 * i; double time_spent = difftime(current.tv_sec, start.tv_sec); double speed = i * write_size; speed /= time_spent; convert_size(buffer_size, 16, speed); printf("\r%*s\r", last_width, clean_line); printf("loop: %lld, current speed %s, done: %.2f%%%n", i, buffer_size, pct / nb_loop, &last_width); fflush(stdout); last = current; } } printf("\r%*s\r", last_width, clean_line); struct timeval end; gettimeofday(&end, 0); clock_gettime(CLOCK_MONOTONIC, ¤t); double time_spent = difftime(current.tv_sec, start.tv_sec); double speed = i * write_size; speed /= time_spent; convert_size(buffer_size, 16, speed); print_time(); printf("Finished, current speed %s\n", buffer_size); struct mtget mt2; failed = ioctl(fd_tape, MTIOCGET, &mt2); if (failed != 0) { printf("MTIOCGET failed => %m\n"); break; } struct mtop eof = { MTWEOF, 1 }; failed = ioctl(fd_tape, MTIOCTOP, &eof); if (failed != 0) { printf("Weof failed => %m\n"); break; } struct mtop nop = { MTNOP, 1 }; failed = ioctl(fd_tape, MTIOCTOP, &nop); if (failed != 0) { printf("Nop failed => %m\n"); break; } failed = ioctl(fd_tape, MTIOCGET, &mt2); if (failed != 0) { printf("MTIOCGET failed => %m\n"); break; } if (!no_rewind) { if (mt.mt_fileno < 2) { rewind_tape(fd_tape); } else { print_time(); print_flush("Moving backward space 1 file... "); static struct mtop rewind = { MTBSFM, 2 }; failed = ioctl(fd_tape, MTIOCTOP, &rewind); if (failed != 0) printf("Failed => %m\n"); else printf("done\n"); } } failed = ioctl(fd_tape, MTIOCGET, &mt2); if (failed) printf("MTIOCGET failed => %m\n"); if (current_block_size > 0 || write_error) break; } close(fd_tape); for (j = 0; j < 32; j++) free(buffer[j]); return 0; }