/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*------------------------------------------------------------------------- * * Created: atomic_reader.c * * Purpose: This is the "reader" part of the standalone test to check * atomic read-write operation on a system. * a) atomic_reader.c--the reader (this file) * a) atomic_writer.c--the writer * c) atomic_data--the name of the data file used by writer and reader * *------------------------------------------------------------------------- */ /***********/ /* Headers */ /***********/ #include #include #include #include #if !defined(WIN32) && !defined(__MINGW32__) #include #include #include #include /****************/ /* Local Macros */ /****************/ #define FILENAME "atomic_data" #define READ_TRIES 20 #define OPEN_TRIES 50 /********************/ /* Local Prototypes */ /********************/ static void usage(void); int verify(int fd, unsigned int k); void print_info(int *info, unsigned int lastr, unsigned iteration); /*------------------------------------------------------------------------- * Function: usage * * Purpose: To print the command line options * * Parameters: None * * Return: void * *------------------------------------------------------------------------- */ static void usage(void) { printf("\n"); printf("Usage error!\n"); printf("Usage: atomic_reader -n -i \n"); printf(" Note**The number of integers for option n has to be positive\n"); printf(" Note**The number of integers for option i has to be positive\n"); printf("\n"); } /* usage() */ /*------------------------------------------------------------------------- * Function: verify * * Purpose: To verify that the data read is the pattern expected. * Each integer read should be the same as the index. * When a difference is encountered, the remaining integers * read should be the same as the previous index. * For example, the pattern expected should be either: * a) 01234567....n-1 * or * b) if at index 4, a difference is encountered, * the remaining integers should be all "3"s as: * 012333333333333 * * Parameters: * fd -- the file descriptor * k -- the number of integers to read * * Return: * positive on success * negative on failure * *------------------------------------------------------------------------- */ int verify(int fd, unsigned int k) { unsigned int i; /* local index variable */ ssize_t bytes_read; /* the number of bytes read */ unsigned int *buf = NULL; /* buffer to hold data read */ /* Allocate buffer for data read */ if ((buf = (unsigned int *)malloc(k * sizeof(unsigned int))) == NULL) { printf("READER: error from malloc\n"); goto error; } /* end if */ /* Position the file at the beginning */ if (lseek(fd, (off_t)0, SEEK_SET) < 0) { printf("READER: error from lseek\n"); goto error; } /* end if */ /* Read the whole file */ if ((bytes_read = read(fd, buf, (k * sizeof(unsigned int)))) < 0) { printf("READER: error from read\n"); goto error; } /* end if */ /* Verify the bytes read are correct */ if (bytes_read != (ssize_t)(k * sizeof(unsigned int))) { printf("READER: error from bytes read=%lu\n", (unsigned long)bytes_read); goto error; } /* end if */ /* Verify data read */ for (i = 0; i < k; i++) { if (buf[i] != i) break; } /* end for */ if (i < k) { /* Compare the beginning and ending sentinel values */ if (buf[k - 1] != (i - 1)) { printf("FAIL IN READER: ...beginning sentinel value=%u, i=%u\n", (i - 1), i); printf("FAIL IN READER: buf[%u]=%u\n", i - 1, buf[i - 1]); printf("FAIL IN READER: buf[%u]=%u\n", i, buf[i]); printf("FAIL IN READER: buf[%u]=%u\n", i + 1, buf[i + 1]); printf("FAIL IN READER: ...ending sentinel value=%u\n", buf[k - 1]); goto error; } /* end if */ } /* end if */ /* Free the buffer */ if (buf) free(buf); return 0; error: /* Free the buffer */ if (buf) free(buf); return -1; } /* end verify() */ /*------------------------------------------------------------------------- * Function: print_info * * Purpose: To print the statistics gathered for re-reads * * Parameters: * info -- the array storing the statistics for re-reads * lastr -- the last read completed * iteration -- the current iteration * * Return: void * *------------------------------------------------------------------------- */ void print_info(int *info, unsigned int lastr, unsigned iteration) { unsigned j; /* local index variable */ printf("--------statistics for %u reads (iteration %u)--------\n", lastr, iteration); for (j = 0; j <= READ_TRIES; j++) printf("# of %u re-tries = %u\n", j, info[j]); printf("--------end statistics for %u reads (iteration %u)--------\n", lastr, iteration); } /* print_info() */ /*------------------------------------------------------------------------- * Function: main * * Purpose: To verify that the data read is the pattern expected. * (1) Make sure the file opens successfully and the # of bytes read is as expected * (2) Iterate the reader with i iterations * (3) Read and verify n integers for each iteration * (4) On verification error, re-read the data at most READ_TRIES * times to see if correct data can be obtained * (5) Print out statistics for the number of re-retries for each iteration * * Note: * (a) The # of integers (via -n option) used by the writer and reader should be the same. * (b) The data file used by the writer and reader should be the same. * * Future enhancement: * 1) Provide default values for n and i and allow user to run with either 0 or 1 option * 2) Use HDF library HD instead of the system calls * 3) Handle large sized buffer (gigabytes) if needed * * Return: Success: EXIT_SUCCESS * Failure: EXIT_FAILURE * *------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { int fd = -1; /* file descriptor */ unsigned int j = 0, i = 0, m = 0; /* local index variables */ int temp; /* temporary variable */ unsigned int iterations = 0; /* the input for "-i" */ unsigned num = 0; /* the input for "-n" */ int opt = 0; /* option char */ int info[READ_TRIES + 1]; /* re-tries statistics */ /* Ensure the expected # of arguments */ if (argc != 5) { usage(); exit(EXIT_FAILURE); } /* end if */ /* Parse command line options */ while ((opt = getopt(argc, argv, "n:i:")) != -1) { switch (opt) { case 'n': if ((temp = atoi(optarg)) < 0) { usage(); exit(EXIT_FAILURE); } /* end if */ num = (unsigned int)temp; break; case 'i': if ((temp = atoi(optarg)) < 0) { usage(); exit(EXIT_FAILURE); } /* end if */ iterations = (unsigned int)temp; break; default: printf("Invalid option encountered\n"); break; } /* end switch */ } /* end while */ printf("READER: number of integers to read = %u; # of iterations = %d\n", num, iterations); printf("\n"); for (i = 1; i <= iterations; i++) { unsigned opens = OPEN_TRIES; printf("READER: *****start iteration %u*****\n", i); /* Ensure open and file size are done properly */ while (opens--) { struct stat sinfo; memset(&sinfo, 0, sizeof(sinfo)); if ((fd = open(FILENAME, O_RDONLY, 0644)) < 0) { printf("READER: error from open--retry open again\n"); } else { printf("READER: open succeed\n"); if ((fstat(fd, &sinfo) == 0) && (sinfo.st_size == (off_t)(num * sizeof(unsigned int)))) { printf("READER: file size is correct--%u\n", (unsigned int)sinfo.st_size); break; } /* end if */ printf("READER: error from fstat or file size of %u is incorrect--retry open again\n", (unsigned int)sinfo.st_size); if (close(fd) < 0) { printf("READER: error from close\n"); return EXIT_FAILURE; } /* end if */ fd = -1; } /* end else */ } /* end while */ if (fd < 0) { printf("READER: *****open failure/incorrect file size for all %u tries, continue next " "iteration*****\n\n", OPEN_TRIES); continue; } /* end if */ memset(info, 0, sizeof(info)); /* Read and verify data */ for (j = 1; j <= num; j++) { printf("READER: doing read %u\n", j); if (verify(fd, num) < 0) { printf("READER: error from read %u\n", j); /* Perform re-read to see if correct data is obtained */ for (m = 1; m <= READ_TRIES; m++) { printf("READER: ===============going to do re-read try %u\n", m); if (verify(fd, num) < 0) printf("READER: ===============error from re-read try %u\n", m); else { ++info[m]; printf("READER: ===============SUCCESS from re-read try %u\n", m); break; } /* end else */ } /* end for */ if (m > READ_TRIES) { printf("READER: ===============error from all re-read tries: %u\n", READ_TRIES); printf("READER:*****ERROR--stop on read %u\n", j); break; } /* end if */ } else { ++info[0]; printf("READER: success from read %u\n", j); } /* end else */ } /* end for */ /* Print the statistics for re-reads */ print_info(info, j - 1, i); /* Close the file */ if (close(fd) < 0) { printf("READER: error from close\n"); return EXIT_FAILURE; } /* end if */ printf("READER: *****end iteration %u*****\n\n", i); } /* end for */ return EXIT_SUCCESS; } #else /* WIN32 / MINGW32 */ int main(void) { printf("Non-POSIX platform. Exiting.\n"); return EXIT_FAILURE; } /* end main() */ #endif /* WIN32 / MINGW32 */